From 159680049285793099fe207c1dd0a6c39c645cb7 Mon Sep 17 00:00:00 2001
From: natha
Date: Fri, 18 Jul 2025 16:35:53 -0300
Subject: [PATCH 01/11] FAQ push
---
src/frontend/static/frontend/package.json | 2 +-
src/frontend/static/frontend/rspack.common.js | 3 +-
src/frontend/static/frontend/rspack.prod.js | 2 +-
.../frontend/src/components/MainNavbar.tsx | 13 ++-
.../frontend/src/components/faq/FAQ.tsx | 83 +++++++++++++++++++
5 files changed, 99 insertions(+), 4 deletions(-)
create mode 100644 src/frontend/static/frontend/src/components/faq/FAQ.tsx
diff --git a/src/frontend/static/frontend/package.json b/src/frontend/static/frontend/package.json
index fd73478c..a2af0b70 100644
--- a/src/frontend/static/frontend/package.json
+++ b/src/frontend/static/frontend/package.json
@@ -57,7 +57,7 @@
"@visx/scale": "^3.5.0",
"@visx/stats": "^3.5.0",
"@visx/tooltip": "^3.3.0",
- "apexcharts": "^3.52.0",
+ "apexcharts": "^4.0.0",
"axios": "^1.8.4",
"cytoscape": "^3.30.2",
"d3": "^7.9.0",
diff --git a/src/frontend/static/frontend/rspack.common.js b/src/frontend/static/frontend/rspack.common.js
index e7f41f91..13bdbbf8 100644
--- a/src/frontend/static/frontend/rspack.common.js
+++ b/src/frontend/static/frontend/rspack.common.js
@@ -26,7 +26,8 @@ export const common = {
survival: `${PATHS.src}/survival.tsx`,
aboutUs: `${PATHS.src}/about-us.tsx`,
openSource: `${PATHS.src}/open-source.tsx`,
- sitePolicy: `${PATHS.src}/site-policy.tsx`
+ sitePolicy: `${PATHS.src}/site-policy.tsx`,
+ faq: `${PATHS.src}/faq.tsx`
},
output: {
path: PATHS.output,
diff --git a/src/frontend/static/frontend/rspack.prod.js b/src/frontend/static/frontend/rspack.prod.js
index ac78fe38..e35b42e1 100644
--- a/src/frontend/static/frontend/rspack.prod.js
+++ b/src/frontend/static/frontend/rspack.prod.js
@@ -1,4 +1,4 @@
-import { common } from './rspack.common.js'
+import { common } from './'
export default {
...common,
diff --git a/src/frontend/static/frontend/src/components/MainNavbar.tsx b/src/frontend/static/frontend/src/components/MainNavbar.tsx
index 508735f1..84ab549a 100644
--- a/src/frontend/static/frontend/src/components/MainNavbar.tsx
+++ b/src/frontend/static/frontend/src/components/MainNavbar.tsx
@@ -150,7 +150,7 @@ const LogInLogOutPanel = (props: LogInLogOutPanelProps) => {
)
}
-type ActiveItemOptions = 'home' | 'pipeline' | 'files' | 'cgds' | 'survival' | 'institutions' | 'about-us' | 'biomarkers' | 'open-source' | 'differential-expression'
+type ActiveItemOptions = 'home' | 'pipeline' | 'files' | 'cgds' | 'survival' | 'institutions' | 'about-us' | 'biomarkers' | 'open-source' | 'differential-expression' | 'faq'
interface MainNavbarProps {
activeItem?: ActiveItemOptions,
@@ -298,6 +298,17 @@ const MainNavbar = (props: MainNavbarProps) => {
+
+
+ FAQ
+
+
+
Open source
diff --git a/src/frontend/static/frontend/src/components/faq/FAQ.tsx b/src/frontend/static/frontend/src/components/faq/FAQ.tsx
new file mode 100644
index 00000000..082675ab
--- /dev/null
+++ b/src/frontend/static/frontend/src/components/faq/FAQ.tsx
@@ -0,0 +1,83 @@
+import React from 'react'
+import { Base } from '../Base'
+import { Container, Divider, Grid, Header, HeaderSubheader, List, ListContent, ListDescription, ListHeader, ListIcon, ListItem } from 'semantic-ui-react'
+
+export const FAQ = () => {
+ return (
+
+
+
+ {/* Git hub */}
+
+
+
+ At Omicsdatascience , we believe in open science. Explore our open-source projects, freely available to the community to foster collaboration, transparency, and innovation in biomedical research. Avilable in our GitHub organization .
+
+
+ These repositories represent some of our most prominent open-source initiatives, developed to empower the research community with accessible and cutting-edge bioinformatics tools.
+
+
+
+
+
+ Multiomix
+ Cloud-based platform to infer cancer genomic and epigenomic events associated with gene expression modulation.
+
+
+
+
+
+ Modulector
+ Modulector is a performing open platform that provides information about miRNAs, genes and methylation sites based on a compilation of information from different resources.
+
+
+
+
+
+ BioApi
+ A powerful abstraction of genomics databases. Bioapi is a REST API that provides data related to gene nomenclature, gene expression, and metabolic pathways.
+
+
+
+
+
+
+
+
+
+ In addition to our open-source software, we regularly publish peer-reviewed scientific articles that document the methodologies, innovations, and findings behind our tools. We invite you to explore our publications to better understand the research impact of our work.
+
+
+
+
+
+
+ Multiomix
+
+
+ A cloud-based platform to infer cancer genomic and epigenomic events associated with gene expression modulation
+
+
+
+
+
+
+
+ Modulector
+
+
+ Una plataforma como servicio para el acceso a bases de datos de micro ARNs
+
+
+
+
+
+
+
+
+
+
+ )
+}
\ No newline at end of file
From 32845e60d5c724468f46938b89c768f21f06d4fe Mon Sep 17 00:00:00 2001
From: Genaro Camele
Date: Mon, 21 Jul 2025 18:17:08 -0300
Subject: [PATCH 02/11] Added missing file
---
src/frontend/static/frontend/src/components/faq/FAQ.tsx | 2 +-
src/frontend/static/frontend/src/faq.tsx | 8 ++++++++
2 files changed, 9 insertions(+), 1 deletion(-)
create mode 100644 src/frontend/static/frontend/src/faq.tsx
diff --git a/src/frontend/static/frontend/src/components/faq/FAQ.tsx b/src/frontend/static/frontend/src/components/faq/FAQ.tsx
index 082675ab..b8969f75 100644
--- a/src/frontend/static/frontend/src/components/faq/FAQ.tsx
+++ b/src/frontend/static/frontend/src/components/faq/FAQ.tsx
@@ -80,4 +80,4 @@ export const FAQ = () => {
)
-}
\ No newline at end of file
+}
diff --git a/src/frontend/static/frontend/src/faq.tsx b/src/frontend/static/frontend/src/faq.tsx
new file mode 100644
index 00000000..7c41060f
--- /dev/null
+++ b/src/frontend/static/frontend/src/faq.tsx
@@ -0,0 +1,8 @@
+import React from 'react'
+import { createRoot } from 'react-dom/client'
+import { FAQ } from './components/faq/FAQ'
+
+const container = document.getElementById('faq-app')
+const root = createRoot(container!)
+// eslint-disable-next-line @stylistic/jsx-pascal-case
+root.render( )
From ea93d56a1b726bcdcbe2f70fad00e582f33f50e5 Mon Sep 17 00:00:00 2001
From: natha
Date: Thu, 28 Aug 2025 16:41:11 -0300
Subject: [PATCH 03/11] FAQ Components
---
.../frontend/src/components/faq/FAQ.tsx | 142 ++++++++----------
src/frontend/static/frontend/src/faq.tsx | 1 -
src/frontend/templates/frontend/base.html | 1 +
src/frontend/templates/frontend/faq.html | 16 ++
src/frontend/urls.py | 3 +-
src/frontend/views.py | 4 +
6 files changed, 87 insertions(+), 80 deletions(-)
create mode 100644 src/frontend/templates/frontend/faq.html
diff --git a/src/frontend/static/frontend/src/components/faq/FAQ.tsx b/src/frontend/static/frontend/src/components/faq/FAQ.tsx
index b8969f75..bb783695 100644
--- a/src/frontend/static/frontend/src/components/faq/FAQ.tsx
+++ b/src/frontend/static/frontend/src/components/faq/FAQ.tsx
@@ -1,83 +1,69 @@
import React from 'react'
+import { Container, Divider, Grid, Header, Segment, List } from 'semantic-ui-react'
import { Base } from '../Base'
-import { Container, Divider, Grid, Header, HeaderSubheader, List, ListContent, ListDescription, ListHeader, ListIcon, ListItem } from 'semantic-ui-react'
export const FAQ = () => {
- return (
-
-
-
- {/* Git hub */}
-
-
-
- At Omicsdatascience , we believe in open science. Explore our open-source projects, freely available to the community to foster collaboration, transparency, and innovation in biomedical research. Avilable in our GitHub organization .
-
-
- These repositories represent some of our most prominent open-source initiatives, developed to empower the research community with accessible and cutting-edge bioinformatics tools.
-
-
-
-
-
- Multiomix
- Cloud-based platform to infer cancer genomic and epigenomic events associated with gene expression modulation.
-
-
-
-
-
- Modulector
- Modulector is a performing open platform that provides information about miRNAs, genes and methylation sites based on a compilation of information from different resources.
-
-
-
-
-
- BioApi
- A powerful abstraction of genomics databases. Bioapi is a REST API that provides data related to gene nomenclature, gene expression, and metabolic pathways.
-
-
-
-
-
-
-
-
-
- In addition to our open-source software, we regularly publish peer-reviewed scientific articles that document the methodologies, innovations, and findings behind our tools. We invite you to explore our publications to better understand the research impact of our work.
-
-
-
-
-
-
- Multiomix
-
-
- A cloud-based platform to infer cancer genomic and epigenomic events associated with gene expression modulation
-
-
-
-
-
-
-
- Modulector
-
-
- Una plataforma como servicio para el acceso a bases de datos de micro ARNs
-
-
-
-
-
-
-
-
-
-
- )
+ return (
+
+
+
+
+
+ Frequently Asked Questions
+
+
+
+ How are cBioPortal datasets incorporated and preprocessed?
+
+ Datasets from cBioPortal are synchronized regularly to ensure data consistency.
+ If there is an update that we miss, users can contact us directly.
+ Duplicate molecules are removed to keep the dataset clean.
+ Samples without information for a given molecule in a biomarker are excluded from trained models,
+ statistical validations, feature selection experiments, and inference steps.
+
+
+ Clinical data also undergo preprocessing: cases with NaN, empty or Null values are filtered out.
+ Additionally, cases with an event but survival time equal to zero are excluded (pending clarification from cBioPortal).
+
+
+
+
+
+
+ How is user-uploaded data privacy handled?
+
+ Uploaded data is securely stored and only accessible to the uploading user.
+ Once deleted, the data is permanently removed from our servers and cannot be recovered.
+ No third parties have access to private user data.
+
+
+
+
+
+
+ Libraries and Tools with Licenses
+
+ For legal and transparency reasons, we provide a list of third-party libraries and tools used in this platform,
+ along with their respective licenses. This ensures compliance and acknowledgment of the open-source
+ community contributions that power our ecosystem.
+
+
+
+
+
+
+
+
+
+
+
+ )
}
diff --git a/src/frontend/static/frontend/src/faq.tsx b/src/frontend/static/frontend/src/faq.tsx
index 7c41060f..def10ef7 100644
--- a/src/frontend/static/frontend/src/faq.tsx
+++ b/src/frontend/static/frontend/src/faq.tsx
@@ -4,5 +4,4 @@ import { FAQ } from './components/faq/FAQ'
const container = document.getElementById('faq-app')
const root = createRoot(container!)
-// eslint-disable-next-line @stylistic/jsx-pascal-case
root.render( )
diff --git a/src/frontend/templates/frontend/base.html b/src/frontend/templates/frontend/base.html
index 0f2a9378..c12137aa 100644
--- a/src/frontend/templates/frontend/base.html
+++ b/src/frontend/templates/frontend/base.html
@@ -61,6 +61,7 @@
const urlSearchUser = "{% url 'search_user' %}" {# URL to search user view #}
const urlUpdateUser = "{% url 'update_user' %}" {# URL to update user view #}
const currentUserId = "{{ user.id }}"
+ const urlFAQ = "{% url 'faq' %}" {# URL to FAQ page #}
{% render_bundle 'base' 'js' %}
diff --git a/src/frontend/templates/frontend/faq.html b/src/frontend/templates/frontend/faq.html
new file mode 100644
index 00000000..29c94675
--- /dev/null
+++ b/src/frontend/templates/frontend/faq.html
@@ -0,0 +1,16 @@
+{% extends 'frontend/base.html' %}
+{% load static %}
+{% load render_bundle from webpack_loader %}
+
+{% block title %} | FAQ{% endblock %}
+{% block meta_description %}
+Frequently Asked Questions about Multiomix and our platform.
+{% endblock %}
+
+{% block content %}
+
+{% endblock %}
+
+{% block js %}
+ {% render_bundle 'faq' 'js' %}
+{% endblock %}
\ No newline at end of file
diff --git a/src/frontend/urls.py b/src/frontend/urls.py
index eefe99a1..c90eb8ca 100644
--- a/src/frontend/urls.py
+++ b/src/frontend/urls.py
@@ -10,6 +10,7 @@
path('open-source', views.open_source, name='open_source'),
path('site-policy', views.terms_and_privacy_policy_action, name='site_policy'),
path('biomarker', views.biomarker, name='biomarker'),
- path('differential-expression', views.differential_expression, name='differential_expression')
+ path('differential-expression', views.differential_expression, name='differential_expression'),
+ path('faq', views.faq_action, name='faq')
]
diff --git a/src/frontend/views.py b/src/frontend/views.py
index 7243b6c3..a0da3eb5 100644
--- a/src/frontend/views.py
+++ b/src/frontend/views.py
@@ -63,3 +63,7 @@ def differential_expression(request):
def open_source(request):
"""Open source view"""
return render(request, "frontend/open-source.html")
+
+def faq_action(request):
+ """FAQ view"""
+ return render(request, "frontend/faq.html")
From c70c2657b520fd007d669ab70f90a1f788875e14 Mon Sep 17 00:00:00 2001
From: natha
Date: Thu, 25 Sep 2025 23:34:36 -0300
Subject: [PATCH 04/11] FAQ comments added
---
src/frontend/static/frontend/rspack.prod.js | 2 +-
.../frontend/src/components/faq/FAQ.tsx | 66 +++++++++++++------
.../components/faq/FAQQuestionAndAnswer.tsx | 30 +++++++++
3 files changed, 78 insertions(+), 20 deletions(-)
create mode 100644 src/frontend/static/frontend/src/components/faq/FAQQuestionAndAnswer.tsx
diff --git a/src/frontend/static/frontend/rspack.prod.js b/src/frontend/static/frontend/rspack.prod.js
index e35b42e1..ac78fe38 100644
--- a/src/frontend/static/frontend/rspack.prod.js
+++ b/src/frontend/static/frontend/rspack.prod.js
@@ -1,4 +1,4 @@
-import { common } from './'
+import { common } from './rspack.common.js'
export default {
...common,
diff --git a/src/frontend/static/frontend/src/components/faq/FAQ.tsx b/src/frontend/static/frontend/src/components/faq/FAQ.tsx
index bb783695..bae8f591 100644
--- a/src/frontend/static/frontend/src/components/faq/FAQ.tsx
+++ b/src/frontend/static/frontend/src/components/faq/FAQ.tsx
@@ -1,6 +1,13 @@
import React from 'react'
import { Container, Divider, Grid, Header, Segment, List } from 'semantic-ui-react'
import { Base } from '../Base'
+import {FAQQuestionAndAnswer} from "./FAQQuestionAndAnswer";
+
+/**
+ * FAQ Page (Frequently Asked Questions).
+ *
+ * Uses the `FAQQuestionAndAnswer` component to display each questions and answers.
+ */
export const FAQ = () => {
return (
@@ -12,11 +19,15 @@ export const FAQ = () => {
Frequently Asked Questions
-
- How are cBioPortal datasets incorporated and preprocessed?
-
- Datasets from cBioPortal are synchronized regularly to ensure data consistency.
- If there is an update that we miss, users can contact us directly.
+ {/* Question 1: Datasets */}
+
+
+ Datasets from cBioPortal are synchronized regularly to ensure data consistency.
+ If there is an update that we miss, users can contact us directly.
Duplicate molecules are removed to keep the dataset clean.
Samples without information for a given molecule in a biomarker are excluded from trained models,
statistical validations, feature selection experiments, and inference steps.
@@ -25,41 +36,58 @@ export const FAQ = () => {
Clinical data also undergo preprocessing: cases with NaN, empty or Null values are filtered out.
Additionally, cases with an event but survival time equal to zero are excluded (pending clarification from cBioPortal).
-
-
-
-
-
- How is user-uploaded data privacy handled?
+ >
+ }
+ />
+
+ {/* Question 2: Privacy */}
+
Uploaded data is securely stored and only accessible to the uploading user.
Once deleted, the data is permanently removed from our servers and cannot be recovered.
No third parties have access to private user data.
-
+ }
+ />
-
- Libraries and Tools with Licenses
+ {/* Question 3: Licenses */}
+
- For legal and transparency reasons, we provide a list of third-party libraries and tools used in this platform,
+ For legal and transparency reasons, we provide a list of third-party libraries and tools used in this platform,
along with their respective licenses. This ensures compliance and acknowledgment of the open-source
community contributions that power our ecosystem.
+
-
+ }
+ />
-
+ }
+
+ />
diff --git a/src/frontend/static/frontend/src/components/faq/FAQQuestionAndAnswer.tsx b/src/frontend/static/frontend/src/components/faq/FAQQuestionAndAnswer.tsx
new file mode 100644
index 00000000..d7e6e6eb
--- /dev/null
+++ b/src/frontend/static/frontend/src/components/faq/FAQQuestionAndAnswer.tsx
@@ -0,0 +1,30 @@
+import React from "react";
+import { Segment, Header } from "semantic-ui-react";
+
+/**
+ * Props for the FAQQuestionAndAnswer component.
+ */
+interface FAQQuestionAndAnswerProps {
+ /** The unique identifier for the segment */
+ segmentId: string;
+ /** The title of the FAQ question */
+ headerTitle: string;
+ /** The answer content for the FAQ question */
+ answer: React.ReactNode;
+}
+
+/**
+ * Reusable component for displaying a FAQ question and its answer.
+ *
+ * @param props - Object containing `segmentId`, `headerTitle`, and `answer`
+ * @returns A React component that displays a FAQ question and its answer.
+*/
+export const FAQQuestionAndAnswer = (props: FAQQuestionAndAnswerProps) => {
+ const { segmentId, headerTitle, answer } = props;
+ return (
+
+
+ {answer}
+
+ )
+}
From 9009c7df107ac1925b51cd15df29a69b17fd608a Mon Sep 17 00:00:00 2001
From: natharisa
Date: Fri, 26 Dec 2025 11:58:21 -0300
Subject: [PATCH 05/11] Translations
---
src/frontend/static/frontend/package.json | 2 +-
.../src/components/about-us/AboutUs.tsx | 28 +-
.../BiomarkerInferenceExperimentsPanel.tsx | 7 +-
...renceExperimentClinicalAttributeSelect.tsx | 4 +-
.../InferenceExperimentResultMetrics.tsx | 6 +-
.../inference/InferenceExperimentsTable.tsx | 48 +--
.../inference/NewInferenceExperimentModal.tsx | 27 +-
.../SamplesAndGroupsInferenceTable.tsx | 23 +-
.../SamplesAndTimeInferenceCharts.tsx | 6 +-
.../SamplesAndTimeInferenceTable.tsx | 29 +-
.../molecules/CurrentMoleculeDetails.tsx | 6 +-
.../molecules/MoleculesDetailsMenu.tsx | 15 +-
.../molecules/MoleculesTable.tsx | 29 +-
.../GeneOntologyCytoscapeChart.tsx | 45 ++-
.../gene-ontology/GeneOntologyPanel.tsx | 40 +--
.../genes/ActionableCancerGenesPanel.tsx | 5 +-
.../genes/GeneAssociationsNetworkPanel.tsx | 35 +-
.../molecules/genes/GeneInformation.tsx | 14 +-
.../molecules/genes/MetabolicPathways.tsx | 12 +-
.../molecules/genes/PathwaysInformation.tsx | 6 +-
.../methylation/MethylationInformation.tsx | 28 +-
.../NewStatisticalValidationModal.tsx | 22 +-
.../StatisticalValidationMenu.tsx | 12 +-
.../StatisticalValidationsTable.tsx | 44 +--
.../result/SamplesAndGroupsTable.tsx | 14 +-
...tatisticalValidationResultBestFeatures.tsx | 13 +-
...StatisticalValidationResultKaplanMeier.tsx | 38 +--
.../StatisticalValidationResultMetrics.tsx | 26 +-
.../trained-models/NewClusteringModelForm.tsx | 55 ++--
.../static/frontend/src/locales/en.ts | 303 ++++++++++++++++++
.../static/frontend/src/locales/es.ts | 303 ++++++++++++++++++
31 files changed, 960 insertions(+), 285 deletions(-)
create mode 100644 src/frontend/static/frontend/src/locales/en.ts
create mode 100644 src/frontend/static/frontend/src/locales/es.ts
diff --git a/src/frontend/static/frontend/package.json b/src/frontend/static/frontend/package.json
index a2af0b70..fd73478c 100644
--- a/src/frontend/static/frontend/package.json
+++ b/src/frontend/static/frontend/package.json
@@ -57,7 +57,7 @@
"@visx/scale": "^3.5.0",
"@visx/stats": "^3.5.0",
"@visx/tooltip": "^3.3.0",
- "apexcharts": "^4.0.0",
+ "apexcharts": "^3.52.0",
"axios": "^1.8.4",
"cytoscape": "^3.30.2",
"d3": "^7.9.0",
diff --git a/src/frontend/static/frontend/src/components/about-us/AboutUs.tsx b/src/frontend/static/frontend/src/components/about-us/AboutUs.tsx
index 6e26bbb3..6440da30 100644
--- a/src/frontend/static/frontend/src/components/about-us/AboutUs.tsx
+++ b/src/frontend/static/frontend/src/components/about-us/AboutUs.tsx
@@ -1,6 +1,7 @@
import React from 'react'
import { Container, Divider, Grid, Header, Image, List } from 'semantic-ui-react'
import { Base } from '../Base'
+import { useIntl } from 'react-intl'
const EMAILS: string[] = [
'mcabba@gmail.com',
@@ -13,6 +14,7 @@ const EMAILS: string[] = [
* @returns Component
*/
export const AboutUs = () => {
+ const intl = useIntl()
return (
@@ -34,13 +36,13 @@ export const AboutUs = () => {
- Multiomix is the result of interdisciplinary work between members of the following scientific institutions:
+ {intl.formatMessage({ id: 'about.description' })}
-
-
-
+
+
+
@@ -51,12 +53,12 @@ export const AboutUs = () => {
- Project coordination:
+ {intl.formatMessage({ id: 'about.coordination' })}
-
-
+
+
@@ -67,15 +69,15 @@ export const AboutUs = () => {
- Project members
+ {intl.formatMessage({ id: 'about.members.title' })}
- Main contributor: B.Comp.Sc. Genaro Camele
+ {intl.formatMessage({ id: 'about.members.main' })}
- Collaborators: Esp. Hernán Chanfreau, Dr. Sebastián Menazzi, St. Agustín Marraco, B.Comp.Sc. Julián Muhlberger, St. Ramiro Lasorsa, PhD. Waldo Hasperué
+ {intl.formatMessage({ id: 'about.members.collaborators' })}
@@ -87,10 +89,10 @@ export const AboutUs = () => {
{/* Contact */}
- Contact:
+ {intl.formatMessage({ id: 'about.contact.title' })}
- For questions or suggestions please contact us:
+ {intl.formatMessage({ id: 'about.contact.questions' })}
{EMAILS.map((email) => (
@@ -98,7 +100,7 @@ export const AboutUs = () => {
))}
- You can also contact us for creating your research institution. It will let researchers share datasets inside Multiomix.
+ {intl.formatMessage({ id: 'about.contact.institutions' })}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/BiomarkerInferenceExperimentsPanel.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/BiomarkerInferenceExperimentsPanel.tsx
index 3c43ab0a..d4c6bf22 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/BiomarkerInferenceExperimentsPanel.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/BiomarkerInferenceExperimentsPanel.tsx
@@ -7,6 +7,7 @@ import { NewInferenceExperimentModal } from './NewInferenceExperimentModal'
import { InferenceExperimentResultModal } from './InferenceExperimentResultModal'
import ky from 'ky'
import { alertGeneralError } from '../../../../utils/util_functions'
+import { useIntl } from 'react-intl'
declare const urlBiomarkerInferenceExperimentsDetails: string
@@ -23,7 +24,7 @@ interface BiomarkerInferenceExperimentsPanelProps {
*/
export const BiomarkerInferenceExperimentsPanel = (props: BiomarkerInferenceExperimentsPanelProps) => {
const abortController = useRef(new AbortController())
-
+ const intl = useIntl()
const [openModalNewInferenceExperiment, setOpenModalNewInferenceExperiment] = useState(false)
const [openModalResultInferenceExperiment, setOpenModalResultInferenceExperiment] = useState(false)
const [selectedInferenceExperiment, setSelectedInferenceExperiment] = useState
>(null)
@@ -92,7 +93,7 @@ export const BiomarkerInferenceExperimentsPanel = (props: BiomarkerInferenceExpe
return (
}
+ closeIcon={ }
closeOnEscape={false}
centered={false}
closeOnDimmerClick={false}
@@ -100,7 +101,7 @@ export const BiomarkerInferenceExperimentsPanel = (props: BiomarkerInferenceExpe
onClose={closeStatResult}
open={openModalResultInferenceExperiment}
>
-
+
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentClinicalAttributeSelect.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentClinicalAttributeSelect.tsx
index 1ddc75a9..7b5c4baa 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentClinicalAttributeSelect.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentClinicalAttributeSelect.tsx
@@ -67,7 +67,7 @@ export const InferenceExperimentClinicalAttributeSelect = (props: InferenceExper
}, [props.selectedInferenceExperiment.id])
return (
<>
-
+
{ props.setSelectedClinicalAttribute(value as string) }}
- placeholder='Clinical attribute to group by'
+ placeholder='inference.clinicalAttribute.placeholder'
disabled={clinicalAttributesOptions.length === 0}
/>
>
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentResultMetrics.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentResultMetrics.tsx
index 405c5d1f..2d74c9bf 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentResultMetrics.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentResultMetrics.tsx
@@ -2,6 +2,7 @@ import React from 'react'
import { Header, Segment } from 'semantic-ui-react'
import { InferenceExperimentForTable } from '../../types'
import { ModelDetailsPanel } from '../ModelDetailsPanels'
+import { useIntl } from 'react-intl'
// declare const urlInferenceExperimentMetrics: string
@@ -17,15 +18,16 @@ interface InferenceExperimentResultMetricsProps {
* @returns Component
*/
export const InferenceExperimentResultMetrics = (props: InferenceExperimentResultMetricsProps) => {
+ const intl = useIntl()
return (
<>
- "{props.selectedInferenceExperiment.name}" metrics
+ {intl.formatMessage({ id: 'inference.metrics.title' }, { name: props.selectedInferenceExperiment.name })}
{/* Model details. */}
-
+ {intl.formatMessage({ id: 'inference.model.details' })}
{props.selectedInferenceExperiment.trained_model !== null &&
}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentsTable.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentsTable.tsx
index 1cbb1fbd..946309b0 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentsTable.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentsTable.tsx
@@ -11,6 +11,7 @@ import { Nullable } from '../../../../utils/interfaces'
import { StopExperimentButton } from '../../../pipeline/all-experiments-view/StopExperimentButton'
import { DeleteButton } from '../../../common/DeleteButton'
import { TableCellSources } from '../../../common/TableCellSources'
+import { useIntl } from 'react-intl'
declare const urlBiomarkerInferenceExperiments: string
declare const urlStopInferenceExperiment: string
@@ -31,6 +32,7 @@ interface InferenceExperimentsTableProps {
* @returns Component.
*/
export const InferenceExperimentsTable = (props: InferenceExperimentsTableProps) => {
+ const intl = useIntl()
const [stoppingInferenceExperiment, setStoppingInferenceExperiment] = useState(false)
const [inferenceExperimentToStop, setInferenceExperimentToStop] = useState>(null)
@@ -109,13 +111,13 @@ export const InferenceExperimentsTable = (props: InferenceExperimentsTableProps)
return (
-
+
- Are you sure you want to stop the inference experiment {inferenceExperimentToStop.name} ?
+ {intl.formatMessage({ id: 'inference.stop.confirm' }, { name: inferenceExperimentToStop.name })}
- Cancel
+ {intl.formatMessage({ id: 'common.cancel' })}
- Stop
+ {intl.formatMessage({ id: 'common.stop' })}
@@ -141,16 +143,16 @@ export const InferenceExperimentsTable = (props: InferenceExperimentsTableProps)
return (
-
+
- Are you sure you want to delete the inference experiment {inferenceExperimentToRemove.name} ?
+ {intl.formatMessage({ id: 'inference.delete.confirm' }, { name: inferenceExperimentToRemove.name })}
- Cancel
+ {intl.formatMessage({ id: 'common.cancel' })}
- Delete
+ {intl.formatMessage({ id: 'common.delete' })}
@@ -165,24 +167,25 @@ export const InferenceExperimentsTable = (props: InferenceExperimentsTableProps)
{/* Modal to confirm deleting the InferenceExperiment */}
{getDeletionConfirmModal()}
- headerTitle='Inference experiments'
+ headerTitle={intl.formatMessage({ id: 'inference.experiments.table.title' })}
headers={[
- { name: 'Name', serverCodeToSort: 'name', width: 3 },
- { name: 'Description', serverCodeToSort: 'description', width: 4 },
- { name: 'State', serverCodeToSort: 'state', textAlign: 'center' },
- { name: 'Model', serverCodeToSort: 'model', width: 1 },
- { name: 'Date', serverCodeToSort: 'created' },
- { name: 'Datasets' },
- { name: 'Actions' }
+ { name: intl.formatMessage({ id: 'inference.table.columns.name' }), serverCodeToSort: 'name', width: 3 },
+ { name: intl.formatMessage({ id: 'inference.table.columns.description' }), serverCodeToSort: 'description', width: 4 },
+ { name: intl.formatMessage({ id: 'inference.table.columns.state' }), serverCodeToSort: 'state', textAlign: 'center' },
+ { name: intl.formatMessage({ id: 'inference.table.columns.model' }), serverCodeToSort: 'model', width: 1 },
+ { name: intl.formatMessage({ id: 'inference.table.columns.date' }), serverCodeToSort: 'created' },
+ { name: intl.formatMessage({ id: 'inference.table.columns.dataset' }) },
+ { name: intl.formatMessage({ id: 'inference.table.columns.actions' }) }
+
]}
queryParams={{ biomarker_pk: props.selectedBiomarker.id }}
defaultSortProp={{ sortField: 'created', sortOrderAscendant: false }}
showSearchInput
- searchLabel='Name'
- searchPlaceholder='Search by name or description'
+ searchLabel={intl.formatMessage({ id: 'inference.search.label' })}
+ searchPlaceholder={intl.formatMessage({ id: 'inference.search.placeholder' })}
urlToRetrieveData={urlBiomarkerInferenceExperiments}
customElements={[
-
+
{ props.setOpenModalNewInferenceExperiment(true) }}>
@@ -219,14 +222,15 @@ export const InferenceExperimentsTable = (props: InferenceExperimentsTableProps)
onClick={() => { props.openInferenceResult(inferenceExperiment) }}
className='clickable'
color='blue'
- title='See results'
+ title={intl.formatMessage({ id: 'inference.results.tooltip' })}
+
/>
)}
{/* Stop button */}
{isInProcess && (
setInferenceExperimentToStop(inferenceExperiment)}
/>
)}
@@ -235,7 +239,7 @@ export const InferenceExperimentsTable = (props: InferenceExperimentsTableProps)
{/* Todo: Revisar ownerid */}
{!isInProcess && (
setInferenceExperimentToRemove(inferenceExperiment)}
ownerId={null}
/>
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/NewInferenceExperimentModal.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/NewInferenceExperimentModal.tsx
index 22ddb004..61aaac85 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/NewInferenceExperimentModal.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/NewInferenceExperimentModal.tsx
@@ -7,6 +7,7 @@ import { SourceSelectors } from '../../../common/SourceSelectors'
import { DjangoCGDSStudy, DjangoUserFile } from '../../../../utils/django_interfaces'
import { BiomarkerTrainedModelsTable } from '../BiomarkerTrainedModelsTable'
import ky from 'ky'
+import { useIntl } from 'react-intl'
declare const urlSubmitInferenceExperiment: string
@@ -56,6 +57,7 @@ const getDefaultNewInferenceExperimentData = (): NewInferenceExperimentData => (
* @returns Component
*/
export const NewInferenceExperimentModal = (props: NewInferenceExperimentModalProps) => {
+ const intl = useIntl()
const [form, setForm] = useState(getDefaultNewInferenceExperimentData())
const [currentStep, setCurrentStep] = useState(1)
const [sendingData, setSendingData] = useState(false)
@@ -292,7 +294,7 @@ export const NewInferenceExperimentModal = (props: NewInferenceExperimentModalPr
return (
}
+ closeIcon={ }
closeOnEscape={false}
centered={false}
closeOnDimmerClick={false}
@@ -302,7 +304,7 @@ export const NewInferenceExperimentModal = (props: NewInferenceExperimentModalPr
>
- Create new inference experiment
+ {intl.formatMessage({ id: 'inference.new.title' })}
@@ -311,27 +313,30 @@ export const NewInferenceExperimentModal = (props: NewInferenceExperimentModalPr
{/* Basic data */}
-
+
+ {intl.formatMessage({ id: 'inference.new.basicData' })}
+
- Required field
+ {intl.formatMessage({ id: 'inference.new.requiredField' })}
+
@@ -341,7 +346,7 @@ export const NewInferenceExperimentModal = (props: NewInferenceExperimentModalPr
1} link onClick={() => { setCurrentStep(1) }}>
- Step 1: Trained model
+ {intl.formatMessage({ id: 'inference.new.step1' })}
- Step 2: molecules datasets
+ {intl.formatMessage({ id: 'inference.new.step2' })}
@@ -378,7 +383,7 @@ export const NewInferenceExperimentModal = (props: NewInferenceExperimentModalPr
color='red'
onClick={() => setCurrentStep(currentStep - 1)}
>
- Go back
+ {intl.formatMessage({ id: 'inference.new.goBack' })}
)}
@@ -392,7 +397,7 @@ export const NewInferenceExperimentModal = (props: NewInferenceExperimentModalPr
}}
disabled={!selectedTrainedModelIsValid}
>
- Continue
+ {intl.formatMessage({ id: 'inference.new.continue' })}
)}
@@ -406,7 +411,7 @@ export const NewInferenceExperimentModal = (props: NewInferenceExperimentModalPr
}}
disabled={!formIsValid()}
>
- Confirm
+ {intl.formatMessage({ id: 'inference.new.confirm' })}
)}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndGroupsInferenceTable.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndGroupsInferenceTable.tsx
index 5a763c07..47a3937c 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndGroupsInferenceTable.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndGroupsInferenceTable.tsx
@@ -5,6 +5,7 @@ import { PaginatedTable } from '../../../common/PaginatedTable'
import { TableCellWithTitle } from '../../../common/TableCellWithTitle'
import { ClusterLabelsSetSelect } from '../../../common/cluster-labels/ClusterLabelsSetSelect'
import { NewClusterLabelsSetModal } from '../../../common/cluster-labels/NewClusterLabelsSetModal'
+import { useIntl } from 'react-intl'
declare const urlInferenceExperimentSamplesAndClusters: string
declare const urlInferenceExperimentSamplesAndClustersDownload: string
@@ -22,6 +23,7 @@ interface SamplesAndGroupsInferenceTableProps {
* @returns Component.
*/
export const SamplesAndGroupsInferenceTable = (props: SamplesAndGroupsInferenceTableProps) => {
+ const intl = useIntl()
const [selectedClusterSetPk, setSelectedClusterSetPk] = useState(undefined)
const [openClusterLabelsSetModal, setOpenClusterLabelsSetModal] = useState(false)
@@ -47,15 +49,16 @@ export const SamplesAndGroupsInferenceTable = (props: SamplesAndGroupsInferenceT
headers={[
- { name: 'Sample', serverCodeToSort: 'sample', width: 3, textAlign: 'center' },
- { name: 'Cluster', serverCodeToSort: 'cluster', width: 2, textAlign: 'center' }
+ { name: intl.formatMessage({ id: 'inference.table.columns.sample' }), serverCodeToSort: 'sample', width: 3, textAlign: 'center' },
+ { name: intl.formatMessage({ id: 'inference.table.columns.cluster' }), serverCodeToSort: 'cluster', width: 2, textAlign: 'center' }
+
]}
queryParams={{
inference_experiment_pk: props.selectedInferenceExperiment.id,
...extraQueryParams
}}
customElements={[
-
+
@@ -63,10 +66,10 @@ export const SamplesAndGroupsInferenceTable = (props: SamplesAndGroupsInferenceT
]}
customFilters={[
{
- label: 'Cluster',
+ label: intl.formatMessage({ id: 'inference.table.filter.cluster.label' }),
keyForServer: 'cluster',
defaultValue: '',
- placeholder: 'Filter by cluster',
+ placeholder: intl.formatMessage({ id: 'inference.table.filter.cluster.placeholder' }),
allowZero: true,
urlToRetrieveOptions: `${urlClustersUniqueInferenceExperiment}/${props.selectedInferenceExperiment.id}/`
}
@@ -74,8 +77,8 @@ export const SamplesAndGroupsInferenceTable = (props: SamplesAndGroupsInferenceT
defaultSortProp={{ sortField: 'sample', sortOrderAscendant: false }}
showSearchInput
defaultPageSize={25}
- searchLabel='Sample'
- searchPlaceholder='Search by sample'
+ searchLabel={intl.formatMessage({ id: 'inference.table.search.label' })}
+ searchPlaceholder={intl.formatMessage({ id: 'inference.table.search.placeholder' })}
urlToRetrieveData={urlInferenceExperimentSamplesAndClusters}
mapFunction={(sampleAndCluster: SampleAndCluster) => {
return (
@@ -88,7 +91,7 @@ export const SamplesAndGroupsInferenceTable = (props: SamplesAndGroupsInferenceT
/>
- {selectedTrainedModelPk !== null && (
+ {selectedTrainedModelPk !== null && (
<>
- { setOpenClusterLabelsSetModal(true) }}>Add Cluster labels
- >
+ { setOpenClusterLabelsSetModal(true) }}>{intl.formatMessage({ id: 'inference.table.addClusterLabels' })}
+ >
)}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndTimeInferenceCharts.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndTimeInferenceCharts.tsx
index c91dd401..0c60893a 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndTimeInferenceCharts.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndTimeInferenceCharts.tsx
@@ -8,6 +8,7 @@ import { alertGeneralError } from '../../../../utils/util_functions'
import { ResultPlaceholder } from '../stat-validations/result/ResultPlaceholder'
import { BoxPlotChart } from '../../../pipeline/experiment-result/gene-gem-details/stats/BoxPlotChart'
import { COLOR_YELLOW_FILL, COLOR_YELLOW_STROKE } from '../../../../utils/constants'
+import { useIntl } from 'react-intl'
declare const urlClinicalSourceAddOrEditInferenceExperiment: string
declare const urlUnlinkClinicalSourceInferenceExperiment: string
@@ -36,6 +37,7 @@ interface SamplesAndTimeInferenceChartsProps {
* @returns Component.
*/
export const SamplesAndTimeInferenceCharts = (props: SamplesAndTimeInferenceChartsProps) => {
+ const intl = useIntl()
const abortController = useRef(new AbortController())
const [loadingChartData, setLoadingChartData] = useState(false)
const [chartData, setChartData] = useState([])
@@ -80,10 +82,10 @@ export const SamplesAndTimeInferenceCharts = (props: SamplesAndTimeInferenceChar
- No clinical attribute selected
+ {intl.formatMessage({ id: 'inference.charts.noAttribute' })}
- Please, select one in the right Select.
+ {intl.formatMessage({ id: 'inference.charts.selectAttribute' })}
)
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndTimeInferenceTable.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndTimeInferenceTable.tsx
index de57c85c..d47aa937 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndTimeInferenceTable.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndTimeInferenceTable.tsx
@@ -9,6 +9,7 @@ import { InfoPopup } from '../../../pipeline/experiment-result/gene-gem-details/
import { SamplesAndTimeInferenceCharts } from './SamplesAndTimeInferenceCharts'
import { InferenceExperimentClinicalAttributeSelect } from './InferenceExperimentClinicalAttributeSelect'
import { ClinicalSourcePopup } from '../../../pipeline/all-experiments-view/ClinicalSourcePopup'
+import { useIntl } from 'react-intl'
declare const urlInferenceExperimentSamplesAndTime: string
declare const urlClinicalSourceAddOrEditInferenceExperiment: string
@@ -28,6 +29,7 @@ interface SamplesAndTimeInferenceTableProps {
* @returns Component.
*/
export const SamplesAndTimeInferenceTable = (props: SamplesAndTimeInferenceTableProps) => {
+ const intl = useIntl()
const [activeMenuItem, setActiveMenuItem] = useState<'table' | 'charts'>('charts') // TODO: change to 'table'
const [selectedRangeSetPk, setSelectedClusterSetPk] = useState(undefined)
const [openRangeLabelsSetModal, setOpenRangeLabelsSetModal] = useState(false)
@@ -48,8 +50,9 @@ export const SamplesAndTimeInferenceTable = (props: SamplesAndTimeInferenceTable
return (
headers={[
- { name: 'Sample', serverCodeToSort: 'sample', width: 3, textAlign: 'center' },
- { name: 'Predicted time', serverCodeToSort: 'prediction', width: 2, textAlign: 'center' }
+ { name: intl.formatMessage({ id: 'inference.timeTable.columns.sample' }), serverCodeToSort: 'sample', width: 3, textAlign: 'center' },
+ { name: intl.formatMessage({ id: 'inference.timeTable.columns.predictedTime' }), serverCodeToSort: 'prediction', width: 2, textAlign: 'center' }
+
]}
queryParams={{
inference_experiment_pk: props.selectedInferenceExperiment.id,
@@ -57,18 +60,18 @@ export const SamplesAndTimeInferenceTable = (props: SamplesAndTimeInferenceTable
}}
customFilters={[
{
- label: 'Range',
+ label: intl.formatMessage({ id: 'inference.timeTable.filter.range.label' }),
keyForServer: 'prediction',
defaultValue: '',
- placeholder: 'Filter by range',
+ placeholder: intl.formatMessage({ id: 'inference.timeTable.filter.range.placeholder' }),
disabledFunction: () => selectedRangeSetPk === undefined
}
]}
defaultSortProp={{ sortField: 'sample', sortOrderAscendant: false }}
showSearchInput
defaultPageSize={25}
- searchLabel='Sample'
- searchPlaceholder='Search by sample'
+ searchLabel={intl.formatMessage({ id: 'inference.timeTable.search.label' })}
+ searchPlaceholder={intl.formatMessage({ id: 'inference.timeTable.search.placeholder' })}
searchWidth={5}
entriesSelectWidth={3}
urlToRetrieveData={urlInferenceExperimentSamplesAndTime}
@@ -116,10 +119,10 @@ export const SamplesAndTimeInferenceTable = (props: SamplesAndTimeInferenceTable
active={activeMenuItem === 'charts'}
onClick={() => setActiveMenuItem('charts')}
>
- Charts
+ {intl.formatMessage({ id: 'inference.timeTable.menu.table' })}
- {selectedTrainedModelPk !== null && (
+ {selectedTrainedModelPk !== null && (
<>
{/* Clinical attribute select */}
- {(activeMenuItem === 'charts' && props.selectedInferenceExperiment.clinical_source_id) && (
+ {(activeMenuItem === 'charts' && props.selectedInferenceExperiment.clinical_source_id) && (
<>
- >
+ >
)}
{/* Range Select */}
@@ -176,8 +179,8 @@ export const SamplesAndTimeInferenceTable = (props: SamplesAndTimeInferenceTable
setSelectedClusterSetPk={setSelectedClusterSetPk}
/>
- { setOpenRangeLabelsSetModal(true) }}>Add Range labels
- >
+ { setOpenRangeLabelsSetModal(true) }}>{intl.formatMessage({ id: 'inference.timeTable.addRangeLabels' })}
+ >
)}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/CurrentMoleculeDetails.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/CurrentMoleculeDetails.tsx
index 4f463eeb..50231679 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/CurrentMoleculeDetails.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/CurrentMoleculeDetails.tsx
@@ -11,6 +11,7 @@ import { GeneAssociationsNetworkPanel } from './genes/GeneAssociationsNetworkPan
import { MiRNADrugsPanel } from '../../../pipeline/experiment-result/gene-gem-details/MiRNADrugsPanel'
import { MiRNADiseasesPanel } from '../../../pipeline/experiment-result/gene-gem-details/MiRNADiseasesPanel'
import { ActionableCancerGenesPanel } from './genes/ActionableCancerGenesPanel'
+import { useIntl } from 'react-intl'
// const MENU_DEFAULT: ActiveBiomarkerMoleculeItemMenu = ActiveBiomarkerMoleculeItemMenu.DETAILS // TODO: use this
const MENU_DEFAULT: ActiveBiomarkerMoleculeItemMenu = ActiveBiomarkerMoleculeItemMenu.DETAILS
@@ -31,6 +32,7 @@ interface CurrentMoleculeDetailsProps {
*/
export const CurrentMoleculeDetails = (props: CurrentMoleculeDetailsProps) => {
const [activeItem, setActiveItem] = useState(MENU_DEFAULT)
+ const intl = useIntl()
/** Effect to set the active item to DETAILS when the selected molecule changes. */
useEffect(() => {
@@ -98,10 +100,10 @@ export const CurrentMoleculeDetails = (props: CurrentMoleculeDetailsProps) => {
- No molecule selected
+ {intl.formatMessage({ id: 'currentMoleculeDetails.noSelection' })}
- Select one in the left panel
+ {intl.formatMessage({ id: 'currentMoleculeDetails.selectOne' })}
)
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/MoleculesDetailsMenu.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/MoleculesDetailsMenu.tsx
index 5a98008b..ea118238 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/MoleculesDetailsMenu.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/MoleculesDetailsMenu.tsx
@@ -3,6 +3,7 @@ import { Menu } from 'semantic-ui-react'
import { InfoPopup } from '../../../pipeline/experiment-result/gene-gem-details/InfoPopup'
import { ActiveBiomarkerMoleculeItemMenu, BiomarkerMolecule } from '../../types'
import { MoleculeType } from '../../../../utils/interfaces'
+import { useIntl } from 'react-intl'
/** MoleculesDetailsMenu props. */
interface MoleculesDetailsMenuProps {
@@ -29,13 +30,13 @@ interface ItemMenuProp {
*/
export const MoleculesDetailsMenu = (props: MoleculesDetailsMenuProps) => {
const isGene = [MoleculeType.MRNA, MoleculeType.CNA].includes(props.selectedMolecule.type)
-
+ const intl = useIntl()
/**
* Array with all the items and conditions
*/
const items: ItemMenuProp[] = [
{
- name: 'Details',
+ name: intl.formatMessage({ id: 'moleculesDetailsMenu.details' }),
onClick: () => props.setActiveItem(ActiveBiomarkerMoleculeItemMenu.DETAILS),
isActive: props.activeItem === ActiveBiomarkerMoleculeItemMenu.DETAILS,
popupInfo: `Details of ${props.selectedMolecule.identifier} obtained from different standardized sources`,
@@ -50,14 +51,14 @@ export const MoleculesDetailsMenu = (props: MoleculesDetailsMenuProps) => {
// isVisible: isGene
// },
{
- name: 'Gene associations network',
+ name: intl.formatMessage({ id: 'moleculesDetailsMenu.geneAssociations' }),
onClick: () => props.setActiveItem(ActiveBiomarkerMoleculeItemMenu.GENE_ASSOCIATIONS_NETWORK),
isActive: props.activeItem === ActiveBiomarkerMoleculeItemMenu.GENE_ASSOCIATIONS_NETWORK,
popupInfo: 'It shows the network of gene associations of the genes of this biomarker',
isVisible: isGene
},
{
- name: 'Gene Ontology',
+ name: intl.formatMessage({ id: 'moleculesDetailsMenu.geneOntology' }),
onClick: () => props.setActiveItem(ActiveBiomarkerMoleculeItemMenu.GENE_ONTOLOGY),
isActive: props.activeItem === ActiveBiomarkerMoleculeItemMenu.GENE_ONTOLOGY,
popupInfo: 'Gene Ontology (GO) is a powerful tool for understanding the biological processes, molecular functions, and cellular components associated with a gene',
@@ -72,21 +73,21 @@ export const MoleculesDetailsMenu = (props: MoleculesDetailsMenuProps) => {
// isVisible: isGene
// },
{
- name: 'Diseases',
+ name: intl.formatMessage({ id: 'moleculesDetailsMenu.diseases' }),
onClick: () => props.setActiveItem(ActiveBiomarkerMoleculeItemMenu.DISEASES),
isActive: props.activeItem === ActiveBiomarkerMoleculeItemMenu.DISEASES,
popupInfo: 'Interactions of the molecule with diseases that have been reported in the literature',
isVisible: [MoleculeType.MIRNA].includes(props.selectedMolecule.type)
},
{
- name: 'Drugs',
+ name: intl.formatMessage({ id: 'moleculesDetailsMenu.drugs' }),
onClick: () => props.setActiveItem(ActiveBiomarkerMoleculeItemMenu.DRUGS),
isActive: props.activeItem === ActiveBiomarkerMoleculeItemMenu.DRUGS,
popupInfo: 'Interactions of the molecule with drugs that have been reported in the literature',
isVisible: [MoleculeType.MIRNA].includes(props.selectedMolecule.type)
},
{
- name: 'miRNA-Gene interactions',
+ name: intl.formatMessage({ id: 'moleculesDetailsMenu.miRNAGeneInteractions' }),
onClick: () => props.setActiveItem(ActiveBiomarkerMoleculeItemMenu.MIRNA_GENE_INTERACTIONS),
isActive: props.activeItem === ActiveBiomarkerMoleculeItemMenu.MIRNA_GENE_INTERACTIONS,
popupInfo: 'Different miRNA-Gene interactions that have been reported in the literature along with the associated mirDIP score and Pubmed sources',
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/MoleculesTable.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/MoleculesTable.tsx
index dc1b9d23..b58bb72e 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/MoleculesTable.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/MoleculesTable.tsx
@@ -5,6 +5,7 @@ import { PaginatedTable } from '../../../common/PaginatedTable'
import { TableCellWithTitle } from '../../../common/TableCellWithTitle'
import { MoleculeTypeLabel } from '../../labels/MoleculeTypeLabel'
import { MoleculeType, Nullable } from '../../../../utils/interfaces'
+import { useIntl } from 'react-intl'
declare const urlBiomarkerMolecules: string
@@ -18,35 +19,35 @@ interface MoleculesTableProps {
openMoleculeDetails: (molecule: BiomarkerMolecule) => void
}
-const moleculesTypesOptions: DropdownItemProps[] = [
- { key: MoleculeType.MRNA, text: 'mRNA', value: MoleculeType.MRNA },
- { key: MoleculeType.MIRNA, text: 'miRNA', value: MoleculeType.MIRNA },
- { key: MoleculeType.CNA, text: 'CNA', value: MoleculeType.CNA },
- { key: MoleculeType.METHYLATION, text: 'Methylation', value: MoleculeType.METHYLATION }
-]
-
/**
* Renders a Table with the samples and the cluster where they belong.
* @param props Component props.
* @returns Component.
*/
export const MoleculesTable = (props: MoleculesTableProps) => {
+ const intl = useIntl()
+ const moleculesTypesOptions: DropdownItemProps[] = [
+ { key: MoleculeType.MRNA, text: intl.formatMessage({ id: 'moleculesTable.type.mrna' }), value: MoleculeType.MRNA },
+ { key: MoleculeType.MIRNA, text: intl.formatMessage({ id: 'moleculesTable.type.mirna' }), value: MoleculeType.MIRNA },
+ { key: MoleculeType.CNA, text: intl.formatMessage({ id: 'moleculesTable.type.cna' }), value: MoleculeType.CNA },
+ { key: MoleculeType.METHYLATION, text: intl.formatMessage({ id: 'moleculesTable.type.methylation' }), value: MoleculeType.METHYLATION }
+ ]
return (
headers={[
- { name: 'Identifier', serverCodeToSort: 'identifier', width: 3 },
- { name: 'Type', serverCodeToSort: 'type', width: 2 },
- { name: 'Actions' }
+ { name: intl.formatMessage({ id: 'moleculesTable.header.identifier' }), serverCodeToSort: 'identifier', width: 3 },
+ { name: intl.formatMessage({ id: 'moleculesTable.header.type' }), serverCodeToSort: 'type', width: 2 },
+ { name: intl.formatMessage({ id: 'moleculesTable.header.actions' }) }
]}
queryParams={{ biomarker_pk: props.selectedBiomarker.id }}
customFilters={[
- { label: 'Type', keyForServer: 'type', defaultValue: '', options: moleculesTypesOptions, width: 6 }
+ { label: intl.formatMessage({ id: 'moleculesTable.header.type' }), keyForServer: 'type', defaultValue: '', options: moleculesTypesOptions, width: 6 }
]}
defaultSortProp={{ sortField: 'identifier', sortOrderAscendant: true }}
showSearchInput
defaultPageSize={25}
- searchLabel='Sample'
- searchPlaceholder='Search by identifier'
+ searchLabel={intl.formatMessage({ id: 'moleculesTable.search.label' })}
+ searchPlaceholder={intl.formatMessage({ id: 'moleculesTable.search.placeholder' })}
urlToRetrieveData={urlBiomarkerMolecules}
searchWidth={6}
entriesSelectWidth={3}
@@ -61,7 +62,7 @@ export const MoleculesTable = (props: MoleculesTableProps) => {
name='chart bar'
className='clickable'
color='blue'
- title='Details'
+ title={intl.formatMessage({ id: 'moleculesTable.details' })}
onClick={() => props.openMoleculeDetails(molecule)}
/>
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/gene-ontology/GeneOntologyCytoscapeChart.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/gene-ontology/GeneOntologyCytoscapeChart.tsx
index 9b277bba..d1c94702 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/gene-ontology/GeneOntologyCytoscapeChart.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/gene-ontology/GeneOntologyCytoscapeChart.tsx
@@ -6,6 +6,7 @@ import { alertGeneralError } from '../../../../../utils/util_functions'
import { OntologyRelationTermToTermFilter, CytoscapeElements, OntologyType, GoTermToTermSearchParams, GoTermToTermForm } from './types'
import { Button, Form, Grid } from 'semantic-ui-react'
import '../../../../../css/cytoscape.css'
+import { useIntl } from 'react-intl'
declare const urlGOTermToTerms: string
@@ -20,18 +21,27 @@ const COLORS_BY_ONTOLOGY_RELATION = {
* Renders the legends for the Cytoscape instance.
* @returns Component.
*/
-const CytoscapeLegends = () => (
-
-
Relations
-
-
- {Object.entries(COLORS_BY_ONTOLOGY_RELATION).map(([_, [relationDescription, color]]) => (
- {relationDescription}
- ))}
-
+const CytoscapeLegends = () => {
+ const intl = useIntl()
+
+ return (
+
+
+ {intl.formatMessage({ id: 'geneOntology.legend.relations' })}
+
+
+
+ {Object.entries(COLORS_BY_ONTOLOGY_RELATION).map(([_, [relationDescription, color]]) => (
+
+
+ {relationDescription}
+
+ ))}
+
+
-
-)
+ )
+}
/** GeneOntologyCytoscapeChart props. */
interface GeneOntologyCytoscapeChartProps {
@@ -47,6 +57,7 @@ interface GeneOntologyCytoscapeChartProps {
* @returns Component.
*/
export const GeneOntologyCytoscapeChart = (props: GeneOntologyCytoscapeChartProps) => {
+ const intl = useIntl()
const abortControllerTerm = useRef(new AbortController())
const [termsRelatedToTermForm, setTermsRelatedToTermForm] = useState
({
relations: [OntologyRelationTermToTermFilter.PART_OF, OntologyRelationTermToTermFilter.REGULATES, OntologyRelationTermToTermFilter.HAS_PART],
@@ -188,12 +199,12 @@ export const GeneOntologyCytoscapeChart = (props: GeneOntologyCytoscapeChartProp
{/* Go back button. */}
-
+
{/* Form for termsRelatedToTermForm */}
- Relations
+ {intl.formatMessage({ id: 'geneOntology.form.relations' })}
{Object.entries(OntologyRelationTermToTermFilter)
.filter(([_key, value]) => value !== OntologyRelationTermToTermFilter.IS_A)
.map(([key, value]) => (
@@ -206,7 +217,7 @@ export const GeneOntologyCytoscapeChart = (props: GeneOntologyCytoscapeChartProp
))}
- Ontology type
+ {intl.formatMessage({ id: 'geneOntology.form.ontologyType' })}
{Object.entries(OntologyType).map(([key, value]) => (
handleChangesInForm('general_depth', parseInt(e.target.value))}
/>
handleChangesInForm('hierarchical_depth_to_children', parseInt(e.target.value))}
/>
handleChangesInForm('to_root', termsRelatedToTermForm.to_root === 1 ? 0 : 1)}
/>
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/gene-ontology/GeneOntologyPanel.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/gene-ontology/GeneOntologyPanel.tsx
index 433a06f1..b851a8e3 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/gene-ontology/GeneOntologyPanel.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/gene-ontology/GeneOntologyPanel.tsx
@@ -7,6 +7,7 @@ import { Nullable } from '../../../../../utils/interfaces'
import { GeneOntologyCytoscapeChart } from './GeneOntologyCytoscapeChart'
import { GORelationType, GeneToTermFilterType, GeneToTermForm, GeneToTermSearchParams, GoTerm, OntologyType, TermsRelatedToGene } from './types'
import { debounce } from 'lodash'
+import { useIntl } from 'react-intl'
// Defined in biomarkers.html
declare const urlGOGeneToTerms: string
@@ -18,6 +19,7 @@ interface GeneOntologyPanelProps {
}
export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
+ const intl = useIntl()
const abortController = useRef(new AbortController())
const [terms, setTerms] = useState>(null)
const [selectedTerm, setSelectedTerm] = useState>(null)
@@ -121,9 +123,9 @@ export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
- Filter type
+ {intl.formatMessage({ id: 'geneOntology.panel.filterType' })}
handleChangesInForm('filter_type', GeneToTermFilterType.INTERSECTION)}
@@ -131,7 +133,7 @@ export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
handleChangesInForm('filter_type', GeneToTermFilterType.UNION)}
@@ -139,7 +141,7 @@ export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
handleChangesInForm('filter_type', GeneToTermFilterType.ENRICHMENT)}
@@ -149,17 +151,17 @@ export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
{termsRelatedToGeneForm.filter_type === GeneToTermFilterType.ENRICHMENT && (
<>
handleChangesInForm('p_value_threshold', value)}
/>
handleChangesInForm('correction_method', value)}
@@ -168,9 +170,9 @@ export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
)}
- Relation type
+ {intl.formatMessage({ id: 'geneOntology.panel.relationType' })}
handleCheckboxChange('relation_type', value)}
@@ -178,7 +180,7 @@ export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
handleCheckboxChange('relation_type', value)}
@@ -186,7 +188,7 @@ export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
handleCheckboxChange('relation_type', value)}
@@ -194,7 +196,7 @@ export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
handleCheckboxChange('relation_type', value)}
@@ -205,7 +207,7 @@ export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
Ontology type
handleCheckboxChange('ontology_type', value)}
@@ -213,7 +215,7 @@ export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
handleCheckboxChange('ontology_type', value)}
@@ -221,7 +223,7 @@ export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
handleCheckboxChange('ontology_type', value)}
@@ -238,8 +240,8 @@ export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
- Term
- Ontology type
+ {intl.formatMessage({ id: 'geneOntology.panel.table.term' })}
+ {intl.formatMessage({ id: 'geneOntology.panel.table.ontologyType' })}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/ActionableCancerGenesPanel.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/ActionableCancerGenesPanel.tsx
index 64c4b305..34ff45e3 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/ActionableCancerGenesPanel.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/ActionableCancerGenesPanel.tsx
@@ -1,7 +1,10 @@
import React from 'react'
+import { useIntl } from 'react-intl'
export const ActionableCancerGenesPanel = () => {
+ const intl = useIntl()
+
return (
- ActionableCancerGenesPanel
+ {intl.formatMessage({ id: 'actionableCancerGenes.panel.title' })}
)
}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/GeneAssociationsNetworkPanel.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/GeneAssociationsNetworkPanel.tsx
index a7d5db85..6b08ec48 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/GeneAssociationsNetworkPanel.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/GeneAssociationsNetworkPanel.tsx
@@ -7,6 +7,7 @@ import { alertGeneralError } from '../../../../../utils/util_functions'
import { InfoPopup } from '../../../../pipeline/experiment-result/gene-gem-details/InfoPopup'
import { ExternalLink } from '../../../../common/ExternalLink'
import '../../../../../css/cytoscape.css'
+import { useIntl } from 'react-intl'
// Defined in biomarkers.html
declare const urlGeneAssociationsNetwork: string
@@ -25,18 +26,27 @@ const COLORS_BY_STRING_RELATION = {
* Renders the legends for the Cytoscape instance.
* @returns Component.
*/
-const CytoscapeLegends = () => (
-
-
Relations
-
-
- {Object.entries(COLORS_BY_STRING_RELATION).map(([_, [relationDescription, color]]) => (
- {relationDescription}
- ))}
-
+const CytoscapeLegends = () => {
+ const intl = useIntl()
+
+ return (
+
+
+ {intl.formatMessage({ id: 'geneAssociations.legend.relations' })}
+
+
+
+ {Object.entries(COLORS_BY_STRING_RELATION).map(([relationKey, [_, color]]) => (
+
+
+ {intl.formatMessage({ id: `geneAssociations.relation.${relationKey}` })}
+
+ ))}
+
+
-
-)
+ )
+}
/** GeneAssociationsNetworkPanel props. */
interface GeneAssociationsNetworkPanelProps {
@@ -45,6 +55,7 @@ interface GeneAssociationsNetworkPanelProps {
}
export const GeneAssociationsNetworkPanel = (props: GeneAssociationsNetworkPanelProps) => {
+ const intl = useIntl()
const abortControllerTerm = useRef(new AbortController())
const [minCombinedScore, setMinCombinedScore] = React.useState(950)
@@ -251,7 +262,7 @@ export const GeneAssociationsNetworkPanel = (props: GeneAssociationsNetworkPanel
- Min combined score
+ {intl.formatMessage({ id: 'geneAssociations.form.minCombinedScore' })}
{
+ const intl = useIntl()
const abortController = useRef(new AbortController())
const [geneData, setGeneData] = useState>(null)
const [loadingData, setLoadingData] = useState(false)
@@ -337,9 +340,10 @@ export const GeneInformation = (props: GeneInformationProps) => {
- No Details found
+ {intl.formatMessage({ id: 'geneInformation.noDetails.title' })}
+
- No Details were found for this gene.
+ {intl.formatMessage({ id: 'geneInformation.noDetails.subtitle' })}
@@ -361,11 +365,11 @@ export const GeneInformation = (props: GeneInformationProps) => {
extra={(
- GRCh37:
+ {intl.formatMessage({ id: 'geneInformation.grch37' })}:
chr{geneData.chromosome} : {geneData.start_GRCh37}-{geneData.end_GRCh37}
- GRCh38:
+ {intl.formatMessage({ id: 'geneInformation.grch38' })}:
chr{geneData.chromosome} : {geneData.start_position}-{geneData.end_position}
@@ -375,7 +379,7 @@ export const GeneInformation = (props: GeneInformationProps) => {
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/MetabolicPathways.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/MetabolicPathways.tsx
index d6e65974..23b93f5e 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/MetabolicPathways.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/MetabolicPathways.tsx
@@ -6,6 +6,7 @@ import { ResultPlaceholder } from '../../stat-validations/result/ResultPlacehold
import { DropdownItemProps, Grid, Header, Input, List, SearchProps, Select } from 'semantic-ui-react'
import { InputLabel } from '../../../../common/InputLabel'
import { InfoPopup } from '../../../../pipeline/experiment-result/gene-gem-details/InfoPopup'
+import { useIntl } from 'react-intl'
declare const urlMetabolicPathways: string
@@ -38,6 +39,7 @@ interface MetabolicPathwaysProps {
* @returns Component.
*/
export const MetabolicPathways = (props: MetabolicPathwaysProps) => {
+ const intl = useIntl()
const abortController = useRef(new AbortController())
const [searchInput, setSearchInput] = useState
('')
const [selectedSource, setSelectedSource] = useState(undefined)
@@ -93,21 +95,21 @@ export const MetabolicPathways = (props: MetabolicPathwaysProps) => {
- Metabolic pathways
+ {intl.formatMessage({ id: 'metabolicPathways.header' })}
-
+
{
{
+ const intl = useIntl()
const abortController = useRef(new AbortController())
const [pathwaysData, setPathwaysData] = useState>(null)
const [loadingData, setLoadingData] = useState(false)
@@ -76,9 +78,9 @@ export const PathwaysInformation = (props: PathwaysInformationProps) => {
- No pathways found
+ {intl.formatMessage({ id: 'pathwaysInformation.noPathways.title' })}
- No pathways were found for this gene.
+ {intl.formatMessage({ id: 'pathwaysInformation.noPathways.subtitle' })}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/methylation/MethylationInformation.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/methylation/MethylationInformation.tsx
index 7a6b81f1..09b68827 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/methylation/MethylationInformation.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/methylation/MethylationInformation.tsx
@@ -5,6 +5,7 @@ import { DjangoMethylationDataJSON } from '../../../../../utils/django_interface
import { Nullable, KySearchParams } from '../../../../../utils/interfaces'
import { InfoPopup } from '../../../../pipeline/experiment-result/gene-gem-details/InfoPopup'
import { ExternalLink } from '../../../../common/ExternalLink'
+import { useIntl } from 'react-intl'
declare const urlMethylationData: string
@@ -25,6 +26,7 @@ interface MethylationInformationProps {
* @returns Component.
*/
export const MethylationInformation = (props: MethylationInformationProps) => {
+ const intl = useIntl()
const [methylationData, setMethylationData] = useState>(null)
const [loading, setLoading] = useState(true)
@@ -76,7 +78,8 @@ export const MethylationInformation = (props: MethylationInformationProps) => {
- No details found for this methylation site
+ {intl.formatMessage({ id: 'methylationInformation.noDetails' })}
+
@@ -103,12 +106,12 @@ export const MethylationInformation = (props: MethylationInformationProps) => {
- Methylation Information
+ {intl.formatMessage({ id: 'methylationInformation.header' })}
@@ -119,7 +122,7 @@ export const MethylationInformation = (props: MethylationInformationProps) => {
{methylationData.chromosome_position && (
- Chr. Position: {methylationData.chromosome_position}
+ {intl.formatMessage({ id: 'methylationInformation.chromosomePosition' })} {methylationData.chromosome_position}
)}
@@ -128,20 +131,23 @@ export const MethylationInformation = (props: MethylationInformationProps) => {
- List of islands related to the methylation site according to the UCSC database
+ {intl.formatMessage({ id: 'methylationInformation.infoPopup.ucsc' })}{' '}
+
+ UCSC
+
)}
onTop
/>
- UCSC CpG Islands
+ {intl.formatMessage({ id: 'methylationInformation.header.ucsc' })}
- CpG Island
- Relation
+ {intl.formatMessage({ id: 'methylationInformation.table.cpgIsland' })}
+ {intl.formatMessage({ id: 'methylationInformation.table.relation' })}
@@ -165,14 +171,14 @@ export const MethylationInformation = (props: MethylationInformationProps) => {
onEvent='hover'
/>
- Related genes
+ {intl.formatMessage({ id: 'methylationInformation.header.genes' })}
- Gene
- Regions
+ {intl.formatMessage({ id: 'methylationInformation.table.gene' })}
+ {intl.formatMessage({ id: 'methylationInformation.table.regions' })}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/NewStatisticalValidationModal.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/NewStatisticalValidationModal.tsx
index 7ca63dde..ebd9abf9 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/NewStatisticalValidationModal.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/NewStatisticalValidationModal.tsx
@@ -7,6 +7,7 @@ import { SourceSelectors } from '../../../common/SourceSelectors'
import { DjangoCGDSStudy, DjangoUserFile } from '../../../../utils/django_interfaces'
import { BiomarkerTrainedModelsTable } from '../BiomarkerTrainedModelsTable'
import ky from 'ky'
+import { useIntl } from 'react-intl'
declare const urlNewStatisticalValidation: string
@@ -59,6 +60,7 @@ const getDefaultNewStatisticalValidationData = (): NewStatisticalValidationData
* @returns Component
*/
export const NewStatisticalValidationModal = (props: NewStatisticalValidationModalProps) => {
+ const intl = useIntl()
const [form, setForm] = useState(getDefaultNewStatisticalValidationData())
const [currentStep, setCurrentStep] = useState(1)
const [sendingData, setSendingData] = useState(false)
@@ -309,7 +311,7 @@ export const NewStatisticalValidationModal = (props: NewStatisticalValidationMod
>
- Create new statistical validation
+ {intl.formatMessage({ id: 'newStatValidation.header.create' })}
@@ -318,27 +320,27 @@ export const NewStatisticalValidationModal = (props: NewStatisticalValidationMod
{/* Basic data */}
-
+ {intl.formatMessage({ id: 'newStatValidation.header.basicData' })}
- Required field
+ {intl.formatMessage({ id: 'newStatValidation.form.requiredField' })}
@@ -348,7 +350,7 @@ export const NewStatisticalValidationModal = (props: NewStatisticalValidationMod
1} link onClick={() => { setCurrentStep(1) }}>
- Step 1: Trained model
+ {intl.formatMessage({ id: 'newStatValidation.step.trainedModel' })}
- Step 2: Validation datasets
+ {intl.formatMessage({ id: 'newStatValidation.step.validationDatasets' })}
@@ -385,7 +387,7 @@ export const NewStatisticalValidationModal = (props: NewStatisticalValidationMod
color='red'
onClick={() => setCurrentStep(currentStep - 1)}
>
- Go back
+ {intl.formatMessage({ id: 'common.cancel' })}
)}
@@ -399,7 +401,7 @@ export const NewStatisticalValidationModal = (props: NewStatisticalValidationMod
}}
disabled={!selectedTrainedModelIsValid}
>
- Continue
+ {intl.formatMessage({ id: 'newStatValidation.button.continue' })}
)}
@@ -413,7 +415,7 @@ export const NewStatisticalValidationModal = (props: NewStatisticalValidationMod
}}
disabled={!formIsValid()}
>
- Confirm
+ {intl.formatMessage({ id: 'newStatValidation.button.confirm' })}
)}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/StatisticalValidationMenu.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/StatisticalValidationMenu.tsx
index 784a68b3..38c15668 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/StatisticalValidationMenu.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/StatisticalValidationMenu.tsx
@@ -2,6 +2,7 @@ import React from 'react'
import { Menu } from 'semantic-ui-react'
import { StatisticalValidationForTable, ActiveStatValidationsItemMenu } from '../../types'
import { InfoPopup } from '../../../pipeline/experiment-result/gene-gem-details/InfoPopup'
+import { useIntl } from 'react-intl'
/** StatisticalValidationMenu props. */
interface StatisticalValidationMenuProps {
@@ -19,13 +20,14 @@ interface StatisticalValidationMenuProps {
* @returns Component.
*/
export const StatisticalValidationMenu = (props: StatisticalValidationMenuProps) => {
+ const intl = useIntl()
return (
props.setActiveItem(ActiveStatValidationsItemMenu.BEST_FEATURES)}
>
- Most significant features
+ {intl.formatMessage({ id: 'statValidationMenu.bestFeatures' })}
props.setActiveItem(ActiveStatValidationsItemMenu.KAPLAN_MEIER)}
>
- Kaplan-Meier
+ {intl.formatMessage({ id: 'statValidationMenu.kaplanMeier' })}
props.setActiveItem(ActiveStatValidationsItemMenu.HEATMAP)}
>
- Heatmap
+ {intl.formatMessage({ id: 'statValidationMenu.heatmap' })}
{
+ const intl = useIntl()
const [stoppingStatValidation, setStoppingStatValidation] = useState(false)
const [statValidationToStop, setStatValidationToStop] = useState>(null)
@@ -109,13 +111,13 @@ export const StatisticalValidationsTable = (props: StatisticalValidationsTablePr
return (
-
+
- Are you sure you want to stop the statistical validation {statValidationToStop.name} ?
+ {intl.formatMessage({ id: 'statValidationsTable.stopValidation.confirm' }, { name: statValidationToStop.name })}?
- Cancel
+ {intl.formatMessage({ id: 'common.cancel' })}
- Stop
+ {intl.formatMessage({ id: 'common.stop' })}
@@ -141,16 +143,16 @@ export const StatisticalValidationsTable = (props: StatisticalValidationsTablePr
return (
-
+
- Are you sure you want to delete the statistical validation {statValidationToRemove.name} ?
+ {intl.formatMessage({ id: 'statValidationsTable.deleteValidation.confirm' }, { name: statValidationToRemove.name })}?
- Cancel
+ {intl.formatMessage({ id: 'common.cancel' })}
- Delete
+ {intl.formatMessage({ id: 'common.delete' })}
@@ -167,24 +169,24 @@ export const StatisticalValidationsTable = (props: StatisticalValidationsTablePr
{/* Table */}
- headerTitle='Statistical validations'
+ headerTitle={intl.formatMessage({ id: 'statValidationsTable.headerTitle' })}
headers={[
- { name: 'Name', serverCodeToSort: 'name', width: 3 },
- { name: 'Description', serverCodeToSort: 'description', width: 4 },
- { name: 'State', serverCodeToSort: 'state', textAlign: 'center' },
- { name: 'Model', textAlign: 'center', width: 2 },
- { name: 'Date', serverCodeToSort: 'created' },
- { name: 'Datasets' },
+ { name: intl.formatMessage({ id: 'statValidationsTable.headers.name' }), serverCodeToSort: 'name', width: 3 },
+ { name: intl.formatMessage({ id: 'statValidationsTable.headers.description' }), serverCodeToSort: 'description', width: 4 },
+ { name: intl.formatMessage({ id: 'statValidationsTable.headers.state' }), serverCodeToSort: 'state', textAlign: 'center' },
+ { name: intl.formatMessage({ id: 'statValidationsTable.headers.model' }), textAlign: 'center', width: 2 },
+ { name: intl.formatMessage({ id: 'statValidationsTable.headers.date' }), serverCodeToSort: 'created' },
+ { name: intl.formatMessage({ id: 'statValidationsTable.headers.datasets' }) },
{ name: 'Actions' }
]}
queryParams={{ biomarker_pk: props.selectedBiomarker.id }}
defaultSortProp={{ sortField: 'created', sortOrderAscendant: false }}
showSearchInput
- searchLabel='Name'
- searchPlaceholder='Search by name or description'
+ searchLabel={intl.formatMessage({ id: 'statValidationsTable.search.label' })}
+ searchPlaceholder={intl.formatMessage({ id: 'statValidationsTable.search.placeholder' })}
urlToRetrieveData={urlBiomarkerStatisticalValidations}
customElements={[
-
+
{ props.setOpenModalNewStatValidation(true) }}>
@@ -223,14 +225,14 @@ export const StatisticalValidationsTable = (props: StatisticalValidationsTablePr
onClick={() => { props.openStatResult(statisticalValidation) }}
className='clickable'
color='blue'
- title='See results'
+ title={intl.formatMessage({ id: 'statValidationsTable.actions.seeResults' })}
/>
)}
{/* Stop button */}
{isInProcess && (
setStatValidationToStop(statisticalValidation)}
/>
)}
@@ -239,7 +241,7 @@ export const StatisticalValidationsTable = (props: StatisticalValidationsTablePr
{/** Todo: revisar ownerId */}
{!isInProcess && (
setStatValidationToRemove(statisticalValidation)}
ownerId={null}
/>
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/SamplesAndGroupsTable.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/SamplesAndGroupsTable.tsx
index 751b26b3..4b370bd6 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/SamplesAndGroupsTable.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/SamplesAndGroupsTable.tsx
@@ -3,6 +3,7 @@ import { SampleAndCluster, StatisticalValidationForTable } from '../../../types'
import { Table } from 'semantic-ui-react'
import { PaginatedTable } from '../../../../common/PaginatedTable'
import { TableCellWithTitle } from '../../../../common/TableCellWithTitle'
+import { useIntl } from 'react-intl'
declare const urlStatisticalValidationSamplesAndClusters: string
declare const urlClustersUniqueStatValidation: string
@@ -19,19 +20,20 @@ interface SamplesAndGroupsTableProps {
*/
export const SamplesAndGroupsTable = (props: SamplesAndGroupsTableProps) => {
/* TODO: implement here the colors for background too */
+ const intl = useIntl()
return (
headers={[
- { name: 'Sample', serverCodeToSort: 'sample', width: 3 },
- { name: 'Cluster', serverCodeToSort: 'cluster', width: 2 }
+ { name: intl.formatMessage({ id: 'samplesAndGroupsTable.header.sample' }), serverCodeToSort: 'sample', width: 3 },
+ { name: intl.formatMessage({ id: 'samplesAndGroupsTable.header.cluster' }), serverCodeToSort: 'cluster', width: 2 }
]}
queryParams={{ statistical_validation_pk: props.selectedStatisticalValidation.id }}
customFilters={[
{
- label: 'Cluster',
+ label: intl.formatMessage({ id: 'samplesAndGroupsTable.filter.cluster' }),
keyForServer: 'cluster',
defaultValue: '',
- placeholder: 'Filter by cluster',
+ placeholder: intl.formatMessage({ id: 'samplesAndGroupsTable.filter.cluster.placeholder' }),
allowZero: true,
urlToRetrieveOptions: `${urlClustersUniqueStatValidation}/${props.selectedStatisticalValidation.id}/`
}
@@ -39,8 +41,8 @@ export const SamplesAndGroupsTable = (props: SamplesAndGroupsTableProps) => {
defaultSortProp={{ sortField: 'sample', sortOrderAscendant: false }}
showSearchInput
defaultPageSize={25}
- searchLabel='Sample'
- searchPlaceholder='Search by sample'
+ searchLabel={intl.formatMessage({ id: 'samplesAndGroupsTable.search.label' })}
+ searchPlaceholder={intl.formatMessage({ id: 'samplesAndGroupsTable.search.placeholder' })}
urlToRetrieveData={urlStatisticalValidationSamplesAndClusters}
mapFunction={(sampleAndCluster: SampleAndCluster) => {
return (
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/StatisticalValidationResultBestFeatures.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/StatisticalValidationResultBestFeatures.tsx
index 737039f3..ff1ded6d 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/StatisticalValidationResultBestFeatures.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/StatisticalValidationResultBestFeatures.tsx
@@ -5,6 +5,7 @@ import ky from 'ky'
import { alertGeneralError } from '../../../../../utils/util_functions'
import ReactApexChart from 'react-apexcharts'
import { ResultPlaceholder } from '../result/ResultPlaceholder'
+import { useIntl } from 'react-intl'
/** Epsilon to add to the min/max value of coefficients. */
const EPSILON = 1
@@ -23,6 +24,7 @@ interface StatisticalValidationResultBestFeaturesProps {
* @returns Component
*/
export const StatisticalValidationResultBestFeatures = (props: StatisticalValidationResultBestFeaturesProps) => {
+ const intl = useIntl()
const abortController = useRef(new AbortController())
const [loading, setLoading] = useState(false)
const [statValidationData, setStatValidationData] = useState>(null)
@@ -76,7 +78,7 @@ export const StatisticalValidationResultBestFeatures = (props: StatisticalValida
const moleculesNames = statValidationData ? statValidationData.map((elem) => elem.identifier) : []
const chartSeries: ApexAxisChartSeries = [{
- name: 'Coefficient',
+ name: intl.formatMessage({ id: 'statValidationBestFeatures.series.coefficient' }),
data: coefficients
}]
@@ -111,7 +113,8 @@ export const StatisticalValidationResultBestFeatures = (props: StatisticalValida
},
yaxis: {
title: {
- text: 'Molecule'
+ text: intl.formatMessage({ id: 'statValidationBestFeatures.axis.molecule' })
+
}
},
tooltip: {
@@ -125,14 +128,16 @@ export const StatisticalValidationResultBestFeatures = (props: StatisticalValida
xaxis: {
categories: moleculesNames,
title: {
- text: 'Coefficient'
+ text: intl.formatMessage({ id: 'statValidationBestFeatures.axis.coefficient' })
+
},
type: 'category',
min: Math.ceil(Math.min(...coefficients) - EPSILON),
max: Math.ceil(Math.max(...coefficients) + EPSILON)
},
noData: {
- text: 'No significant features found for this statistical validation'
+ text: intl.formatMessage({ id: 'statValidationBestFeatures.noData' })
+
}
}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/StatisticalValidationResultKaplanMeier.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/StatisticalValidationResultKaplanMeier.tsx
index f8451a88..8cbc556f 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/StatisticalValidationResultKaplanMeier.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/StatisticalValidationResultKaplanMeier.tsx
@@ -9,6 +9,7 @@ import { InfoPopup } from '../../../../pipeline/experiment-result/gene-gem-detai
import { ResultPlaceholder } from './ResultPlaceholder'
import { SamplesAndGroupsTable } from './SamplesAndGroupsTable'
import { debounce } from 'lodash'
+import { useIntl } from 'react-intl'
declare const urlStatisticalValidationKaplanMeierClustering: string
declare const urlStatisticalValidationKaplanMeierByAttr: string
@@ -30,6 +31,7 @@ type KaplanMeierStrategy = 'clustering' | 'clinical_attribute'
* @returns Component
*/
export const StatisticalValidationResultKaplanMeier = (props: StatisticalValidationResultKaplanMeierProps) => {
+ const intl = useIntl()
const abortController = useRef(new AbortController())
const hasClusteringModel = props.selectedStatisticalValidation.fitness_function === FitnessFunction.CLUSTERING
const [loadingKaplanMeier, setLoadingKaplanMeier] = useState(false)
@@ -174,8 +176,8 @@ export const StatisticalValidationResultKaplanMeier = (props: StatisticalValidat
data={kaplanMeierData.groups}
height={480}
width={600}
- xAxisLabel='Time'
- yAxisLabel='Probability'
+ xAxisLabel={intl.formatMessage({ id: 'kaplanMeier.axis.time' })}
+ yAxisLabel={intl.formatMessage({ id: 'kaplanMeier.axis.probability' })}
/>
)
}
@@ -194,16 +196,16 @@ export const StatisticalValidationResultKaplanMeier = (props: StatisticalValidat
{/* Clustering metrics. */}
-
+ {intl.formatMessage({ id: 'kaplanMeier.header.clusteringMetrics' })}
setKaplanMeierStrategy('clustering')}
active={kaplanMeierStrategy === 'clustering'}
>
- Clustering model
+ {intl.formatMessage({ id: 'kaplanMeier.button.clusteringModel' })}
setKaplanMeierStrategy('clinical_attribute')}
active={kaplanMeierStrategy === 'clinical_attribute'}
>
- Group by clinical
+ {intl.formatMessage({ id: 'kaplanMeier.button.groupByClinical' })}
-
+
)}
{/* Clinical attribute select */}
- {(!hasClusteringModel || kaplanMeierStrategy === 'clinical_attribute') && (
+ {(!hasClusteringModel || kaplanMeierStrategy === 'clinical_attribute') && (
{ setSelectedClinicalAttribute(value as string) }}
- placeholder='Clinical attribute to group by'
+ placeholder={intl.formatMessage({ id: 'kaplanMeier.select.clinicalAttribute' })}
disabled={clinicalAttributesOptions.length === 0}
- />
+ />
)}
{/* TODO: add InfoPopups for every metric and their interpretation. */}
{kaplanMeierData ? kaplanMeierData.concordance_index.toFixed(3) : '-'}
- C-Index
+ {intl.formatMessage({ id: 'kaplanMeier.metric.cIndex' })}
{kaplanMeierData ? kaplanMeierData.log_likelihood.toFixed(3) : '-'}
- Partial Log-Likelihood
+ {intl.formatMessage({ id: 'kaplanMeier.metric.partialLogLikelihood' })}
{/* Samples and clusters modal. */}
- {(hasClusteringModel && kaplanMeierStrategy === 'clustering' && kaplanMeierData !== null) && (
+ {(hasClusteringModel && kaplanMeierStrategy === 'clustering' && kaplanMeierData !== null) && (
setShowSamplesAndClusters(false)}
onOpen={() => setShowSamplesAndClusters(true)}
closeIcon={ }
open={showSamplesAndClusters}
- trigger={See samples and clusters }
+ trigger={{intl.formatMessage({ id: 'kaplanMeier.button.seeSamplesAndClusters' })} }
>
- Samples and clusters
+ {intl.formatMessage({ id: 'kaplanMeier.modal.samplesAndClusters' })}
- setShowSamplesAndClusters(false)}>Close
+ setShowSamplesAndClusters(false)}>{intl.formatMessage({ id: 'common.close' })}
-
+
)}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/StatisticalValidationResultMetrics.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/StatisticalValidationResultMetrics.tsx
index a749ca9c..a69fb325 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/StatisticalValidationResultMetrics.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/StatisticalValidationResultMetrics.tsx
@@ -5,6 +5,7 @@ import ky from 'ky'
import { alertGeneralError } from '../../../../../utils/util_functions'
import { Header, Placeholder, Segment, Statistic } from 'semantic-ui-react'
import { ModelDetailsPanel } from '../../ModelDetailsPanels'
+import { useIntl } from 'react-intl'
declare const urlStatisticalValidationMetrics: string
@@ -20,6 +21,7 @@ interface StatisticalValidationResultMetricsProps {
* @returns Component
*/
export const StatisticalValidationResultMetrics = (props: StatisticalValidationResultMetricsProps) => {
+ const intl = useIntl()
const abortController = useRef(new AbortController())
const [loadingMetrics, setLoadingMetrics] = useState(false)
const [statValidationData, setStatValidationData] = useState>(null)
@@ -72,21 +74,21 @@ export const StatisticalValidationResultMetrics = (props: StatisticalValidationR
return (
<>
- "{props.selectedStatisticalValidation.name}" metrics
+ "{props.selectedStatisticalValidation.name}" {intl.formatMessage({ id: 'statValidationMetrics.header.metrics' })}
{/* Model details. */}
-
+ {intl.formatMessage({ id: 'statValidationMetrics.header.modelDetails' })}
{props.selectedStatisticalValidation.trained_model !== null &&
}
{/* Result metrics data. */}
- {!isClustering && (
+ {!isClustering && (
- {loadingMetrics && (
+ {loadingMetrics && (
@@ -96,28 +98,28 @@ export const StatisticalValidationResultMetrics = (props: StatisticalValidationR
-
+
)}
- {(!loadingMetrics && statValidationData !== null) && (
+ {(!loadingMetrics && statValidationData !== null) && (
<>
-
+ {intl.formatMessage({ id: 'statValidationMetrics.header.validationMetrics' })}
{statValidationData.mean_squared_error ? statValidationData.mean_squared_error.toFixed(3) : '-'}
- MSE
+ {intl.formatMessage({ id: 'statValidationMetrics.metric.mse' })}
{statValidationData.c_index ? statValidationData.c_index.toFixed(3) : '-'}
- C-Index
+ {intl.formatMessage({ id: 'statValidationMetrics.metric.cIndex' })}
{statValidationData.r2_score ? statValidationData.r2_score.toFixed(3) : '-'}
- R2 score
+ {intl.formatMessage({ id: 'statValidationMetrics.metric.r2Score' })}
- >
+ >
)}
-
+
)}
>
)
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/trained-models/NewClusteringModelForm.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/trained-models/NewClusteringModelForm.tsx
index cdbf9014..dc12fc04 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/trained-models/NewClusteringModelForm.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/trained-models/NewClusteringModelForm.tsx
@@ -4,6 +4,7 @@ import { clusteringAlgorithmOptions, clusteringMetricOptions, clusteringScoringM
import { ClusteringMetric, ClusteringParameters } from '../../types'
import { InfoPopup } from '../../../pipeline/experiment-result/gene-gem-details/InfoPopup'
import { InputLabel } from '../../../common/InputLabel'
+import { useIntl } from 'react-intl'
interface NewClusteringModelFormProps {
/** Getter of the selected params to handle in the form. */
@@ -15,22 +16,16 @@ interface NewClusteringModelFormProps {
}
export const NewClusteringModelForm = (props: NewClusteringModelFormProps) => {
+ const intl = useIntl()
return (
<>
+
- K-Means: Groups data by minimizing intra-cluster variance; effective for clustering RNA and miRNA expression profiles.
- Spectral Clustering: Uses graph-based similarity to identify complex patterns; ideal for integrating methylation and CNA data.
- BK-Means: A hierarchical variation of K-Means, suitable for layered clustering of clinical and multi-omics datasets.
- Ward’s Method: Minimizes variance in hierarchical clustering; well-suited for combining RNA and methylation data in integrated analyses.
- >
- )}
+ content={intl.formatMessage({ id: 'newClusteringForm.info.algorithm' })}
onTop={false}
onEvent='hover'
noBorder
@@ -39,7 +34,7 @@ export const NewClusteringModelForm = (props: NewClusteringModelFormProps) => {
)}
options={clusteringAlgorithmOptions}
- placeholder='Select an algorithm'
+ placeholder={intl.formatMessage({ id: 'newClusteringForm.placeholder.algorithm' })}
name='algorithm'
value={props.parameters.algorithm}
onChange={props.handleChangeParams}
@@ -48,16 +43,16 @@ export const NewClusteringModelForm = (props: NewClusteringModelFormProps) => {
{ props.handleChangeOptimalNClusters(checked ?? false) }}
- label='Search for the optimal number of clusters'
+ label={intl.formatMessage({ id: 'newClusteringForm.label.searchOptimalClusters' })}
/>
{!props.parameters.lookForOptimalNClusters && (
+
{
fluid
selectOnBlur={false}
label={(
-
+
- Cox Regression: A proportional hazards model to identify associations between multi-omics features (RNA, miRNA, methylation) and clinical outcomes over time.
- Log-Rank Test: A non-parametric test to compare the survival distributions of two or more groups; currently not available.
- >
- )}
+ content={intl.formatMessage({ id: 'newClusteringForm.info.metric' })}
onTop={false}
onEvent='hover'
noBorder
@@ -93,7 +83,7 @@ export const NewClusteringModelForm = (props: NewClusteringModelFormProps) => {
)}
options={clusteringMetricOptions}
- placeholder='Select a metric'
+ placeholder={intl.formatMessage({ id: 'newClusteringForm.placeholder.metric' })}
name='metric'
value={props.parameters.metric}
onChange={props.handleChangeParams}
@@ -105,14 +95,9 @@ export const NewClusteringModelForm = (props: NewClusteringModelFormProps) => {
fluid
selectOnBlur={false}
label={(
-
+
- C-Index: A measure of concordance between predicted and observed survival outcomes; higher values indicate better model performance.
- Log Likelihood: The probability of observing the data given the model; lower values indicate better model performance.
- >
- )}
+ content={intl.formatMessage({ id: 'newClusteringForm.info.scoringMethod' })}
onTop={false}
onEvent='hover'
noBorder
@@ -121,7 +106,7 @@ export const NewClusteringModelForm = (props: NewClusteringModelFormProps) => {
)}
options={clusteringScoringMethodOptions}
- placeholder='Select a method'
+ placeholder={intl.formatMessage({ id: 'newClusteringForm.placeholder.scoringMethod' })}
name='scoringMethod'
value={props.parameters.scoringMethod}
onChange={props.handleChangeParams}
@@ -131,9 +116,9 @@ export const NewClusteringModelForm = (props: NewClusteringModelFormProps) => {
+
{
/>
)}
- placeholder='An integer number'
+ placeholder={intl.formatMessage({ id: 'newClusteringForm.placeholder.integer' })}
type='number'
step={1}
min={0}
@@ -152,9 +137,9 @@ export const NewClusteringModelForm = (props: NewClusteringModelFormProps) => {
+
{
/>
)}
- placeholder='An integer number'
+ placeholder={intl.formatMessage({ id: 'newClusteringForm.placeholder.integer' })}
type='number'
step={0.1}
min={0}
diff --git a/src/frontend/static/frontend/src/locales/en.ts b/src/frontend/static/frontend/src/locales/en.ts
new file mode 100644
index 00000000..116f72a4
--- /dev/null
+++ b/src/frontend/static/frontend/src/locales/en.ts
@@ -0,0 +1,303 @@
+export default {
+ // common actions
+ 'common.cancel': 'Cancel',
+ 'common.delete': 'Delete',
+ 'common.stop': 'Stop',
+ 'common.save': 'Save',
+ 'common.close': 'Close',
+
+ // Auth/user
+ 'auth.login': 'Log in',
+ 'auth.greeting': 'Hi, {username}',
+ 'auth.editProfile': 'Edit profile',
+ 'auth.logout': 'Exit',
+
+ // Menús
+ 'menu.analysis': 'Analysis',
+ 'menu.gem': 'GEM',
+ 'menu.gem.tooltip': 'Gene Expression Modulation',
+ 'menu.biomarkers': 'Biomarkers',
+ 'menu.datasets': 'Datasets',
+ 'menu.multiomix': 'Multiomix',
+ 'menu.cbioportal': 'cBioPortal',
+ 'menu.institutions': 'Institutions',
+ 'menu.admin': 'Admin',
+ 'menu.admin.genes': 'Database: Genes',
+ 'menu.about': 'About us',
+ 'menu.faq': 'Frequently Asked Questions',
+ 'menu.opensource': 'Open Source',
+
+ // About us
+ 'about.description': 'Multiomix is the result of interdisciplinary work between members of the following scientific institutions:',
+ 'about.institution.caeti': 'CAETI - Universidad Abierta Interamericana',
+ 'about.institution.ciniba': 'CINIBA - Faculty of Medical Sciences - UNLP',
+ 'about.institution.lidi': 'LIDI - Faculty of Informatics - UNLP',
+
+ 'about.coordination': 'Project coordination:',
+ 'about.coordinator.Abba': 'PhD Martín Abba',
+ 'about.coordinator.Butti': 'Dr. MSc. Matias Butti',
+
+ 'about.members.title': 'Project members:',
+ 'about.members.main': 'Main contributor: B.Comp.Sc. Genaro Camele',
+ 'about.members.collaborators': 'Collaborators: Esp. Hernán Chanfreau, Dr. Sebastián Menazzi, St. Agustín Marraco, B.Comp.Sc. Julián Muhlberger, St. Ramiro Lasorsa, PhD. Waldo Hasperué',
+
+ 'about.contact.title': 'Contact:',
+ 'about.contact.questions': 'For questions or suggestions please contact us:',
+ 'about.contact.institutions': 'You can also contact us for creating your research institution. It will let researchers share datasets inside Multiomix.',
+
+ // BIOMARKERS
+ // 1.BiomarkerInferenceExperimentsPanel.tsx
+ 'inference.experiment.title': 'Inference experiment "{name}"',
+ // 2.InferenceExperimentClinicalAttributeSelect.tsx label
+ 'inference.clinicalAttribute.label': 'Group by clinical attribute',
+ 'inference.clinicalAttribute.placeholder': 'Clinical attribute to group by',
+ // 3.InferenceExperimentResultMetrics.tsx
+ 'inference.metrics.title': '"{name}" metrics',
+ 'inference.model.details': 'Model details',
+ // 5.InferenceExperimentsTable.tsx
+ 'inference.stop.title': 'Stop inference experiment',
+ 'inference.stop.confirm': 'Are you sure you want to stop the inference experiment "{name}"?',
+ 'inference.stop.cancel': '{common.cancel}',
+ 'inference.stop.button': '{common.stop}',
+
+ 'inference.delete.title': 'Delete experiment',
+ 'inference.delete.confirm': 'Are you sure you want to delete the inference experiment "{name}"?',
+ 'inference.delete.cancel': '{common.cancel}',
+ 'inference.delete.button': '{common.delete}',
+
+ 'inference.table.title': 'Inference experiments',
+ 'inference.table.columns.name': 'Name',
+ 'inference.table.columns.description': 'Description',
+ 'inference.table.columns.state': 'State',
+ 'inference.table.columns.model': 'Model',
+ 'inference.table.columns.date': 'Date',
+ 'inference.table.columns.dataset': 'Datasets',
+ 'inference.table.columns.actions': 'Actions',
+
+ 'inference.search.label': 'Name',
+ 'inference.search.placeholder': 'Search by name or description',
+
+ 'inference.new.title': 'New inference experiment',
+ 'inference.results.title': 'See results',
+ 'inference.results.tooltip': 'View experiment results',
+ // 6.NewInferenceExperimentModal.tsx
+ 'inference.newInference.title': 'Create new inference experiment',
+ 'inference.new.basicData': 'Basic data',
+ 'inference.new.name': 'Name',
+ 'inference.new.description': 'Description (optional)',
+ 'inference.new.requiredField': 'Required field',
+ 'inference.new.step1': 'Step 1: Trained model',
+ 'inference.new.step2': 'Step 2: molecules datasets',
+ 'inference.new.goBack': 'Go back',
+ 'inference.new.continue': 'Continue',
+ 'inference.new.confirm': 'Confirm',
+ // 7.SamplesAndGroupsInferenceTable.tsx
+ 'inference.table.columns.sample': 'Sample',
+ 'inference.table.columns.cluster': 'Cluster',
+ 'inference.table.download.tooltip': 'Download results in a CSV file',
+ 'inference.table.filter.cluster.label': 'Cluster',
+ 'inference.table.filter.cluster.placeholder': 'Filter by cluster',
+ 'inference.table.search.label': 'Sample',
+ 'inference.table.search.placeholder': 'Search by sample',
+ 'inference.table.addClusterLabels': 'Add Cluster labels',
+ // 8.SamplesAndTimeInferenceCharts.tsx
+ 'inference.charts.noAttribute': 'No clinical attribute selected',
+ 'inference.charts.selectAttribute': 'Please, select one in the right Select.',
+ // 9.SamplesAndTimeInferenceTable.tsx
+ 'inference.timeTable.columns.sample': 'Sample',
+ 'inference.timeTable.columns.predictedTime': 'Predicted time',
+ 'inference.timeTable.filter.range.label': 'Range',
+ 'inference.timeTable.filter.range.placeholder': 'Filter by range',
+ 'inference.timeTable.search.label': 'Sample',
+ 'inference.timeTable.search.placeholder': 'Search by sample',
+ 'inference.timeTable.menu.table': 'Table',
+ 'inference.timeTable.menu.charts': 'Charts',
+ 'inference.timeTable.menu.table.info': 'Table with all the samples and their predicted hazard/survival time',
+ 'inference.timeTable.menu.charts.info': 'Shows some charts with the samples and their predicted hazard/survival time grouped by some condition',
+ 'inference.timeTable.addRangeLabels': 'Add Range labels',
+ // 10.molecules/GeneOntologyCytoscapeChart.tsx
+ 'geneOntology.goBack': 'Go back',
+ 'geneOntology.legend.relations': 'Relations',
+ 'geneOntology.form.relations': 'Relations',
+ 'geneOntology.form.ontologyType': 'Ontology type',
+ 'geneOntology.form.generalDepth': 'General depth',
+ 'geneOntology.form.hierarchicalDepth': 'Hierarchical depth to children',
+ 'geneOntology.form.toRoot': 'To root',
+ 'geneOntology.relation.hasPart': 'Has part',
+ 'geneOntology.relation.isA': 'Is a',
+ 'geneOntology.relation.partOf': 'Part of',
+ 'geneOntology.relation.regulates': 'Regulates',
+ // 11.GeneOntologyPanel
+ 'geneOntology.panel.filterType': 'Filter type',
+ 'geneOntology.panel.filterType.intersection': 'Intersection',
+ 'geneOntology.panel.filterType.union': 'Union',
+ 'geneOntology.panel.filterType.enrichment': 'Enrichment',
+ 'geneOntology.panel.pValueThreshold': 'P-value threshold',
+ 'geneOntology.panel.correctionMethod': 'Correction method',
+ 'geneOntology.panel.correctionMethod.analytical': 'Analytical',
+ 'geneOntology.panel.correctionMethod.bonferroni': 'Bonferroni',
+ 'geneOntology.panel.correctionMethod.falseDiscoveryRate': 'False discovery rate',
+ 'geneOntology.panel.relationType': 'Relation type',
+ 'geneOntology.panel.relationType.enables': 'Enables',
+ 'geneOntology.panel.relationType.involvedIn': 'Involved in',
+ 'geneOntology.panel.relationType.partOf': 'Part of',
+ 'geneOntology.panel.relationType.locatedIn': 'Located in',
+ 'geneOntology.panel.ontologyType': 'Ontology type',
+ 'geneOntology.panel.ontologyType.biologicalProcess': 'Biological process',
+ 'geneOntology.panel.ontologyType.molecularFunction': 'Molecular function',
+ 'geneOntology.panel.ontologyType.cellularComponent': 'Cellular component',
+ 'geneOntology.panel.table.term': 'Term',
+ 'geneOntology.panel.table.ontologyType': 'Ontology type',
+ // 12.GENES.ActionableCancerGenesPanel.tsx
+ 'actionableCancerGenes.panel.title': 'Actionable Cancer Genes Panel',
+ // 13.GeneAssociationsNetworkPanel
+ 'geneAssociations.legend.relations': 'Relations',
+ 'geneAssociations.relation.fusion': 'Fusion',
+ 'geneAssociations.relation.coOccurrence': 'Co-occurrence',
+ 'geneAssociations.relation.experimental': 'Experimental',
+ 'geneAssociations.relation.textMining': 'Text mining',
+ 'geneAssociations.relation.database': 'Database',
+ 'geneAssociations.relation.coExpression': 'Co-expression',
+ 'geneAssociations.form.minCombinedScore': 'Min combined score',
+ 'geneAssociations.infoPopup.text': 'The combined score is computed by combining the probabilities from the different evidence channels and corrected for the probability of randomly observing an interaction. For a more detailed description please see von Mering, et al. Nucleic Acids Res. 2005',
+ // 14.GeneInformation.tsx
+ 'geneInformation.noDetails.title': 'No Details found',
+ 'geneInformation.noDetails.subtitle': 'No Details were found for this gene.',
+ 'geneInformation.summary': 'Summary',
+ 'geneInformation.grch37': 'GRCh37',
+ 'geneInformation.grch38': 'GRCh38',
+ // 15.MetabolicPathwaysPanel.tsx
+ 'metabolicPathways.infoPopup': 'List of genes that are involved in a pathway for a given database',
+ 'metabolicPathways.header': 'Metabolic pathways',
+ 'metabolicPathways.selectSource': 'Select a source',
+ 'metabolicPathways.sourcePlaceholder': 'Source',
+ 'metabolicPathways.searchPlaceholder': 'Search',
+ // 16.PathwaysInformation.tsx
+ 'pathwaysInformation.noPathways.title': 'No pathways found',
+ 'pathwaysInformation.noPathways.subtitle': 'No pathways were found for this gene.',
+ // 17.MethylationInformation.tsx
+ 'methylationInformation.noDetails': 'No details found for this methylation site',
+ 'methylationInformation.infoPopup.aliases': 'Methylation aliases and chromosome position',
+ 'methylationInformation.header': 'Methylation Information',
+ 'methylationInformation.chromosomePosition': 'Chr. Position:',
+ 'methylationInformation.infoPopup.ucsc': 'List of islands related to the methylation site according to the UCSC database',
+ 'methylationInformation.header.ucsc': 'UCSC CpG Islands',
+ 'methylationInformation.table.cpgIsland': 'CpG Island',
+ 'methylationInformation.table.relation': 'Relation',
+ 'methylationInformation.infoPopup.genes': 'Genes related to this methylation site and the regions where the methylation site is located. These regions, according to the NCBI RefSeq database, can be: 5UTR=5\' untranslated region between the Transcription Start Site (TTS) and ATG start site, 3UTR=3\' untranslated region between the stop codon and poly A signal, exon_#, TSS200=1-200 bp 5\' the TSS, or TS1500=200-1500 bp 5\' of the TSS',
+ 'methylationInformation.header.genes': 'Related genes',
+ 'methylationInformation.table.gene': 'Gene',
+ 'methylationInformation.table.regions': 'Regions',
+ // 18.CurrentMoleculeDetails.tsx
+ 'currentMoleculeDetails.noSelection': 'No molecule selected',
+ 'currentMoleculeDetails.selectOne': 'Select one in the left panel',
+ // 19.MoleculesDetailsMenu.tsx
+ 'moleculesDetailsMenu.details': 'Details',
+ 'moleculesDetailsMenu.details.info': 'Details of {identifier} obtained from different standardized sources',
+ 'moleculesDetailsMenu.geneAssociations': 'Gene associations network',
+ 'moleculesDetailsMenu.geneAssociations.info': 'It shows the network of gene associations of the genes of this biomarker',
+ 'moleculesDetailsMenu.geneOntology': 'Gene Ontology',
+ 'moleculesDetailsMenu.geneOntology.info': 'Gene Ontology (GO) is a powerful tool for understanding the biological processes, molecular functions, and cellular components associated with a gene',
+ 'moleculesDetailsMenu.diseases': 'Diseases',
+ 'moleculesDetailsMenu.diseases.info': 'Interactions of the molecule with diseases that have been reported in the literature',
+ 'moleculesDetailsMenu.drugs': 'Drugs',
+ 'moleculesDetailsMenu.drugs.info': 'Interactions of the molecule with drugs that have been reported in the literature',
+ 'moleculesDetailsMenu.miRNAGeneInteractions': 'miRNA-Gene interactions',
+ 'moleculesDetailsMenu.miRNAGeneInteractions.info': 'Different miRNA-Gene interactions that have been reported in the literature along with the associated mirDIP score and Pubmed sources',
+ // 20.MoleculesTable.tsx
+ 'moleculesTable.type.mrna': 'mRNA',
+ 'moleculesTable.type.mirna': 'miRNA',
+ 'moleculesTable.type.cna': 'CNA',
+ 'moleculesTable.type.methylation': 'Methylation',
+ 'moleculesTable.header.identifier': 'Identifier',
+ 'moleculesTable.header.type': 'Type',
+ 'moleculesTable.header.actions': 'Actions',
+ 'moleculesTable.search.label': 'Sample',
+ 'moleculesTable.search.placeholder': 'Search by identifier',
+ 'moleculesTable.details': 'Details',
+ // 21.SamplesAndGroupsTable.tsx
+ 'samplesAndGroupsTable.header.sample': 'Sample',
+ 'samplesAndGroupsTable.header.cluster': 'Cluster',
+ 'samplesAndGroupsTable.filter.cluster': 'Cluster',
+ 'samplesAndGroupsTable.filter.cluster.placeholder': 'Filter by cluster',
+ 'samplesAndGroupsTable.search.label': 'Sample',
+ 'samplesAndGroupsTable.search.placeholder': 'Search by sample',
+ // 22.StatisticalValidationResultBestFeatures.tsx
+ 'statValidationBestFeatures.series.coefficient': 'Coefficient',
+ 'statValidationBestFeatures.axis.molecule': 'Molecule',
+ 'statValidationBestFeatures.axis.coefficient': 'Coefficient',
+ 'statValidationBestFeatures.noData': 'No significant features found for this statistical validation',
+ // 23.StatisticalValidationResultKaplanMeier.tsx
+ 'kaplanMeier.axis.time': 'Time',
+ 'kaplanMeier.axis.probability': 'Probability',
+ 'kaplanMeier.info.coxRegression': 'These metrics are computed using Cox-Regression',
+ 'kaplanMeier.header.clusteringMetrics': 'Clustering metrics',
+ 'kaplanMeier.button.clusteringModel': 'Clustering model',
+ 'kaplanMeier.button.groupByClinical': 'Group by clinical',
+ 'kaplanMeier.select.clinicalAttribute': 'Clinical attribute to group by',
+ 'kaplanMeier.metric.cIndex': 'C-Index',
+ 'kaplanMeier.metric.partialLogLikelihood': 'Partial Log-Likelihood',
+ 'kaplanMeier.button.seeSamplesAndClusters': 'See samples and clusters',
+ 'kaplanMeier.modal.samplesAndClusters': 'Samples and clusters',
+ // 24.StatisticalValidationResultMetrics.tsx
+ 'statValidationMetrics.header.metrics': 'metrics',
+ 'statValidationMetrics.header.modelDetails': 'Model details',
+ 'statValidationMetrics.header.validationMetrics': 'Validation metrics',
+ 'statValidationMetrics.metric.mse': 'MSE',
+ 'statValidationMetrics.metric.r2Score': 'R2 score',
+ // 25.NewStatisticalValidationModal.tsx
+ 'newStatValidation.header.create': 'Create new statistical validation',
+ 'newStatValidation.header.basicData': 'Basic data',
+ 'newStatValidation.form.name': 'Name',
+ 'newStatValidation.form.descriptionOptional': 'Description (optional)',
+ 'newStatValidation.form.requiredField': 'Required field',
+ 'newStatValidation.step.trainedModel': 'Step 1: Trained model',
+ 'newStatValidation.step.validationDatasets': 'Step 2: Validation datasets',
+ 'newStatValidation.button.continue': 'Continue',
+ 'newStatValidation.button.confirm': 'Confirm',
+ // 26.StatisticalValidationMenu.tsx
+ 'statValidationMenu.bestFeatures': 'Most significant features',
+ 'statValidationMenu.bestFeatures.info': 'Most significant features for the survival analysis',
+ 'statValidationMenu.kaplanMeier': 'Kaplan-Meier',
+ 'statValidationMenu.kaplanMeier.info': 'Kaplan-Meier curve showing survival or hazard ratio',
+ 'statValidationMenu.heatmap': 'Heatmap',
+ 'statValidationMenu.heatmap.info': 'Heatmap for every sample and molecule',
+ // 27.StatisticalValidationsTable.tsx
+
+ 'statValidationsTable.stopValidation.header': 'Stop statistical validation',
+ 'statValidationsTable.stopValidation.confirm': 'Are you sure you want to stop the statistical validation {name}?',
+ 'statValidationsTable.deleteValidation.header': 'Delete statistical validation',
+ 'statValidationsTable.deleteValidation.confirm': 'Are you sure you want to delete the statistical validation {name}?',
+ 'statValidationsTable.headerTitle': 'Statistical validations',
+ 'statValidationsTable.headers.name': 'Name',
+ 'statValidationsTable.headers.description': 'Description',
+ 'statValidationsTable.headers.state': 'State',
+ 'statValidationsTable.headers.model': 'Model',
+ 'statValidationsTable.headers.date': 'Date',
+ 'statValidationsTable.headers.datasets': 'Datasets',
+ 'statValidationsTable.headers.actions': 'Actions',
+ 'statValidationsTable.search.label': 'Name',
+ 'statValidationsTable.search.placeholder': 'Search by name or description',
+ 'statValidationsTable.newValidation': 'New statistical validation',
+ 'statValidationsTable.actions.seeResults': 'See results',
+ 'statValidationsTable.actions.stopValidation': 'Stop statistical validation',
+ 'statValidationsTable.actions.deleteValidation': 'Delete statistical validation',
+ // 28.NewClusteringModelForm.tsx
+ 'newClusteringForm.label.algorithm': 'Algorithm',
+ 'newClusteringForm.placeholder.algorithm': 'Select an algorithm',
+ 'newClusteringForm.label.searchOptimalClusters': 'Search for the optimal number of clusters',
+ 'newClusteringForm.label.nClusters': 'Number of clusters',
+ 'newClusteringForm.info.nClusters': 'The number of clusters to group the data into. The optimal number can be found by looking for the elbow in the curve of the sum of squared distances between samples and their closest cluster center.',
+ 'newClusteringForm.label.metric': 'Metric',
+ 'newClusteringForm.placeholder.metric': 'Select a metric',
+ 'newClusteringForm.label.scoringMethod': 'Scoring method',
+ 'newClusteringForm.placeholder.scoringMethod': 'Select a method',
+ 'newClusteringForm.label.randomState': 'Random state',
+ 'newClusteringForm.label.penalizer': 'Penalizer',
+ 'newClusteringForm.placeholder.integer': 'An integer number',
+ 'newClusteringForm.info.algorithm': 'K-Means: Groups data by minimizing intra-cluster variance; effective for RNA and miRNA. Spectral Clustering: Uses graph-based similarity to identify complex patterns; ideal for methylation and CNA. BK-Means: A hierarchical variation of K-Means, suitable for layered clustering of clinical and multi-omics datasets. Ward’s Method: Minimizes variance in hierarchical clustering; well-suited for combining RNA and methylation data.',
+ 'newClusteringForm.info.metric': 'Cox Regression: A proportional hazards model to identify associations between multi-omics features and clinical outcomes. Log-Rank Test: A non-parametric test to compare survival distributions; currently not available.',
+ 'newClusteringForm.info.scoringMethod': 'C-Index: A measure of concordance between predicted and observed survival outcomes; higher values indicate better performance. Log Likelihood: The probability of observing the data given the model; lower values indicate better performance.',
+ 'newClusteringForm.info.randomState': 'The seed used by the random number generator to ensure reproducibility.',
+ 'newClusteringForm.info.penalizer': 'Useful when clinical data has few samples or events; increases robustness and avoids NaN values.',
+}
diff --git a/src/frontend/static/frontend/src/locales/es.ts b/src/frontend/static/frontend/src/locales/es.ts
new file mode 100644
index 00000000..d6093728
--- /dev/null
+++ b/src/frontend/static/frontend/src/locales/es.ts
@@ -0,0 +1,303 @@
+export default {
+ // Common actions
+ 'common.cancel': 'Cancelar',
+ 'common.delete': 'Eliminar',
+ 'common.stop': 'Detener',
+ 'common.save': 'Guardar',
+ 'common.close': 'Cerrar',
+
+ // Auth/usuario
+ 'auth.login': 'Iniciar sesión',
+ 'auth.greeting': 'Hola, {username}',
+ 'auth.editProfile': 'Editar perfil',
+ 'auth.logout': 'Salir',
+
+ // Menús
+ 'menu.analysis': 'Análisis',
+ 'menu.gem': 'GEM',
+ 'menu.gem.tooltip': 'Modulación de Expresión Génica',
+ 'menu.biomarkers': 'Biomarcadores',
+ 'menu.datasets': 'Conjuntos de datos',
+ 'menu.multiomix': 'Multiomix',
+ 'menu.cbioportal': 'cBioPortal',
+ 'menu.institutions': 'Instituciones',
+ 'menu.admin': 'Administración',
+ 'menu.admin.genes': 'Base de datos: Genes',
+ 'menu.about': 'Sobre nosotros',
+ 'menu.faq': 'Preguntas frecuentes',
+ 'menu.opensource': 'Código abierto',
+
+ // About us
+ 'about.description': 'Multiomix es el resultado del trabajo interdisciplinario entre miembros de las siguientes instituciones científicas:',
+ 'about.institution.caeti': 'CAETI - Universidad Abierta Interamericana',
+ 'about.institution.ciniba': 'CINIBA - Facultad de Ciencias Médicas - UNLP',
+ 'about.institution.lidi': 'LIDI - Facultad de Informática - UNLP',
+
+ 'about.coordination': 'Coordinación del proyecto:',
+ 'about.coordinator.Abba': 'PhD Martín Abba',
+ 'about.coordinator.Butti': 'Dr. MSc. Matias Butti',
+
+ 'about.members.title': 'Miembros del proyecto:',
+ 'about.members.main': 'Contribuyente principal: B.Comp.Sc. Genaro Camele',
+ 'about.members.collaborators': 'Colaboradores: Esp. Hernán Chanfreau, Dr. Sebastián Menazzi, St. Agustín Marraco, B.Comp.Sc. Julián Muhlberger, St. Ramiro Lasorsa, PhD. Waldo Hasperué',
+
+ 'about.contact.title': 'Contacto:',
+ 'about.contact.questions': 'Para preguntas o sugerencias, contáctenos:',
+ 'about.contact.institutions': 'También puede contactarnos para crear su institución de investigación. Esto permitirá a los investigadores compartir conjuntos de datos dentro de Multiomix.',
+
+ // BIOMARKERS
+
+ // BiomarkerInferenceExperimentsPanel.tsx
+ 'inference.experiment.title': 'Experimento de interferencia "{name}"',
+ // 2.InferenceExperimentClinicalAttributeSelect.tsx
+ 'inference.clinicalAttribute.label': 'Agrupar por atributo clínico',
+ 'inference.clinicalAttribute.placeholder': 'Atributo clínico para agrupar',
+ // 3.InferenceExperimentResultMetrics.tsx
+ 'inference.metrics.title': 'Métricas de "{name}"',
+ 'inference.model.details': 'Detalles del modelo',
+ // 5.InferenceExperimentsTable.tsx
+ 'inference.stop.title': 'Detener experimento de inferencia',
+ 'inference.stop.confirm': '¿Estás segura de que quieres detener el experimento de inferencia "{name}"?',
+ 'inference.stop.cancel': '{common.cancel}',
+ 'inference.stop.button': '{common.stop}',
+
+ 'inference.delete.title': 'Eliminar experimento',
+ 'inference.delete.confirm': '¿Estás segura de que quieres eliminar el experimento de inferencia "{name}"?',
+ 'inference.delete.cancel': '{common.cancel}',
+ 'inference.delete.button': '{common.delete}',
+
+ 'inference.table.title': 'Experimentos de inferencia',
+ 'inference.table.columns.name': 'Nombre',
+ 'inference.table.columns.description': 'Descripción',
+ 'inference.table.columns.state': 'Estado',
+ 'inference.table.columns.model': 'Modelo',
+ 'inference.table.columns.date': 'Fecha',
+ 'inference.table.columns.dataset': 'Conjuntos de datos',
+ 'inference.table.columns.actions': 'Acciones',
+
+ 'inference.search.label': 'Nombre',
+ 'inference.search.placeholder': 'Buscar por nombre o descripción',
+
+ 'inference.new.title': 'Nuevo experimento de inferencia',
+ 'inference.results.title': 'Ver resultados',
+ 'inference.results.tooltip': 'Eliminar experimento',
+ // 6.NewInferenceExperimentModal.tsx
+ 'inference.newInference.title': 'Crear nuevo experimento de inferencia',
+ 'inference.new.basicData': 'Datos básicos',
+ 'inference.new.name': 'Nombre',
+ 'inference.new.description': 'Descripción (opcional)',
+ 'inference.new.requiredField': 'Campo obligatorio',
+ 'inference.new.step1': 'Paso 1: Modelo entrenado',
+ 'inference.new.step2': 'Paso 2: Conjuntos de datos de moléculas',
+ 'inference.new.goBack': 'Volver',
+ 'inference.new.continue': 'Continuar',
+ 'inference.new.confirm': 'Confirmar',
+ // 7.SamplesAndGroupsInferenceTable.tsx
+ 'inference.table.columns.sample': 'Muestra',
+ 'inference.table.columns.cluster': 'Grupo',
+ 'inference.table.download.tooltip': 'Descargar resultados en un archivo CSV',
+ 'inference.table.filter.cluster.label': 'Grupo',
+ 'inference.table.filter.cluster.placeholder': 'Filtrar por grupo',
+ 'inference.table.search.label': 'Muestra',
+ 'inference.table.search.placeholder': 'Buscar por muestra',
+ 'inference.table.addClusterLabels': 'Agregar etiquetas de grupo',
+ // 8.SamplesAndTimeInferenceCharts.tsx
+ 'inference.charts.noAttribute': 'No se seleccionó ningún atributo clínico',
+ 'inference.charts.selectAttribute': 'Por favor, selecciona uno en el selector de la derecha.',
+ // 9.SamplesAndTimeInferenceTable.tsx
+ 'inference.timeTable.columns.sample': 'Muestra',
+ 'inference.timeTable.columns.predictedTime': 'Tiempo predicho',
+ 'inference.timeTable.filter.range.label': 'Rango',
+ 'inference.timeTable.filter.range.placeholder': 'Filtrar por rango',
+ 'inference.timeTable.search.label': 'Muestra',
+ 'inference.timeTable.search.placeholder': 'Buscar por muestra',
+ 'inference.timeTable.menu.table': 'Tabla',
+ 'inference.timeTable.menu.charts': 'Gráficos',
+ 'inference.timeTable.menu.table.info': 'Tabla con todas las muestras y su tiempo de riesgo/supervivencia predicho',
+ 'inference.timeTable.menu.charts.info': 'Muestra gráficos con las muestras y su tiempo de riesgo/supervivencia predicho agrupado por alguna condición',
+ 'inference.timeTable.addRangeLabels': 'Agregar etiquetas de rango',
+ // 10.molecules/GeneOntologyCytoscapeChart.tsx
+ 'geneOntology.goBack': 'Volver',
+ 'geneOntology.legend.relations': 'Relaciones',
+ 'geneOntology.form.relations': 'Relaciones',
+ 'geneOntology.form.ontologyType': 'Tipo de ontología',
+ 'geneOntology.form.generalDepth': 'Profundidad general',
+ 'geneOntology.form.hierarchicalDepth': 'Profundidad jerárquica hacia hijos',
+ 'geneOntology.form.toRoot': 'Hasta la raíz',
+ 'geneOntology.relation.hasPart': 'Tiene parte',
+ 'geneOntology.relation.isA': 'Es un',
+ 'geneOntology.relation.partOf': 'Parte de',
+ 'geneOntology.relation.regulates': 'Regula',
+ // 11.GeneOntologyPanel
+ 'geneOntology.panel.filterType': 'Tipo de filtro',
+ 'geneOntology.panel.filterType.intersection': 'Intersección',
+ 'geneOntology.panel.filterType.union': 'Unión',
+ 'geneOntology.panel.filterType.enrichment': 'Enriquecimiento',
+ 'geneOntology.panel.pValueThreshold': 'Umbral de valor p',
+ 'geneOntology.panel.correctionMethod': 'Método de corrección',
+ 'geneOntology.panel.correctionMethod.analytical': 'Analítico',
+ 'geneOntology.panel.correctionMethod.bonferroni': 'Bonferroni',
+ 'geneOntology.panel.correctionMethod.falseDiscoveryRate': 'Tasa de descubrimiento falso',
+ 'geneOntology.panel.relationType': 'Tipo de relación',
+ 'geneOntology.panel.relationType.enables': 'Habilita',
+ 'geneOntology.panel.relationType.involvedIn': 'Involucrado en',
+ 'geneOntology.panel.relationType.partOf': 'Parte de',
+ 'geneOntology.panel.relationType.locatedIn': 'Ubicado en',
+ 'geneOntology.panel.ontologyType': 'Tipo de ontología',
+ 'geneOntology.panel.ontologyType.biologicalProcess': 'Proceso biológico',
+ 'geneOntology.panel.ontologyType.molecularFunction': 'Función molecular',
+ 'geneOntology.panel.ontologyType.cellularComponent': 'Componente celular',
+ 'geneOntology.panel.table.term': 'Término',
+ 'geneOntology.panel.table.ontologyType': 'Tipo de ontología',
+ // 12GENES.ActionableCancerGenesPanel.tsx
+ 'actionableGenes.panel.title': 'Panel de genes de cáncer accionables',
+ // 13.GeneAssociationsNetworkPanel
+ 'geneAssociations.legend.relations': 'Relaciones',
+ 'geneAssociations.relation.fusion': 'Fusión',
+ 'geneAssociations.relation.coOccurrence': 'Co-ocurrencia',
+ 'geneAssociations.relation.experimental': 'Experimental',
+ 'geneAssociations.relation.textMining': 'Minería de texto',
+ 'geneAssociations.relation.database': 'Base de datos',
+ 'geneAssociations.relation.coExpression': 'Co-expresión',
+ 'geneAssociations.form.minCombinedScore': 'Puntuación combinada mínima',
+ 'geneAssociations.infoPopup.text': 'La puntuación combinada se calcula combinando las probabilidades de los diferentes canales de evidencia y se corrige por la probabilidad de observar una interacción al azar. Para una descripción más detallada consulte von Mering, et al. Nucleic Acids Res. 2005',
+ // 14.GeneInformation
+ 'geneInformation.noDetails.title': 'No se encontraron detalles',
+ 'geneInformation.noDetails.subtitle': 'No se encontraron detalles para este gen.',
+ 'geneInformation.summary': 'Resumen',
+ 'geneInformation.grch37': 'GRCh37',
+ 'geneInformation.grch38': 'GRCh38',
+ // 15.MetabolicPathwaysPanel.tsx
+ 'metabolicPathways.infoPopup': 'Lista de genes que participan en una vía para una base de datos dada',
+ 'metabolicPathways.header': 'Vías metabólicas',
+ 'metabolicPathways.selectSource': 'Selecciona una fuente',
+ 'metabolicPathways.sourcePlaceholder': 'Fuente',
+ 'metabolicPathways.searchPlaceholder': 'Buscar',
+ // 16.PathwaysInformation.tsx
+ 'pathwaysInformation.noPathways.title': 'No se encontraron vías',
+ 'pathwaysInformation.noPathways.subtitle': 'No se encontraron vías para este gen.',
+ // 17.MethylationInformation.tsx
+ 'methylationInformation.noDetails': 'No se encontraron detalles para este sitio de metilación',
+ 'methylationInformation.infoPopup.aliases': 'Alias de metilación y posición cromosómica',
+ 'methylationInformation.header': 'Información de metilación',
+ 'methylationInformation.chromosomePosition': 'Posición cromosómica:',
+ 'methylationInformation.infoPopup.ucsc': 'Lista de islas relacionadas con el sitio de metilación según la base de datos UCSC',
+ 'methylationInformation.header.ucsc': 'Islas CpG UCSC',
+ 'methylationInformation.table.cpgIsland': 'Isla CpG',
+ 'methylationInformation.table.relation': 'Relación',
+ 'methylationInformation.infoPopup.genes': 'Genes relacionados con este sitio de metilación y las regiones donde se encuentra. Estas regiones, según la base de datos NCBI RefSeq, pueden ser: 5UTR=5\' región no traducida entre el sitio de inicio de transcripción (TTS) y el sitio de inicio ATG, 3UTR=3\' región no traducida entre el codón de parada y la señal poli A, exon_#, TSS200=1-200 pb 5\' del TSS, o TS1500=200-1500 pb 5\' del TSS',
+ 'methylationInformation.header.genes': 'Genes relacionados',
+ 'methylationInformation.table.gene': 'Gen',
+ 'methylationInformation.table.regions': 'Regiones',
+ // 18.CurrentMoleculeDetails.tsx
+ 'currentMoleculeDetails.noSelection': 'Ninguna molécula seleccionada',
+ 'currentMoleculeDetails.selectOne': 'Selecciona una en el panel izquierdo',
+ // 19.MoleculesDetailsMenu.tsx
+ 'moleculesDetailsMenu.details': 'Detalles',
+ 'moleculesDetailsMenu.details.info': 'Detalles de {identifier} obtenidos de diferentes fuentes estandarizadas',
+ 'moleculesDetailsMenu.geneAssociations': 'Red de asociaciones génicas',
+ 'moleculesDetailsMenu.geneAssociations.info': 'Muestra la red de asociaciones génicas de los genes de este biomarcador',
+ 'moleculesDetailsMenu.geneOntology': 'Ontología génica',
+ 'moleculesDetailsMenu.geneOntology.info': 'La Ontología Génica (GO) es una herramienta poderosa para comprender los procesos biológicos, funciones moleculares y componentes celulares asociados a un gen',
+ 'moleculesDetailsMenu.diseases': 'Enfermedades',
+ 'moleculesDetailsMenu.diseases.info': 'Interacciones de la molécula con enfermedades reportadas en la literatura',
+ 'moleculesDetailsMenu.drugs': 'Fármacos',
+ 'moleculesDetailsMenu.drugs.info': 'Interacciones de la molécula con fármacos reportadas en la literatura',
+ 'moleculesDetailsMenu.miRNAGeneInteractions': 'Interacciones miRNA-Gen',
+ 'moleculesDetailsMenu.miRNAGeneInteractions.info': 'Diferentes interacciones miRNA-Gen reportadas en la literatura junto con el puntaje mirDIP y fuentes de PubMed',
+ // 20.MoleculesTable.tsx
+ 'moleculesTable.type.mrna': 'mRNA',
+ 'moleculesTable.type.mirna': 'miRNA',
+ 'moleculesTable.type.cna': 'CNA',
+ 'moleculesTable.type.methylation': 'Metilación',
+ 'moleculesTable.header.identifier': 'Identificador',
+ 'moleculesTable.header.type': 'Tipo',
+ 'moleculesTable.header.actions': 'Acciones',
+ 'moleculesTable.search.label': 'Muestra',
+ 'moleculesTable.search.placeholder': 'Buscar por identificador',
+ 'moleculesTable.details': 'Detalles',
+ // 21.SamplesAndGroupsTable.tsx
+ 'samplesAndGroupsTable.header.sample': 'Muestra',
+ 'samplesAndGroupsTable.header.cluster': 'Cluster',
+ 'samplesAndGroupsTable.filter.cluster': 'Cluster',
+ 'samplesAndGroupsTable.filter.cluster.placeholder': 'Filtrar por cluster',
+ 'samplesAndGroupsTable.search.label': 'Muestra',
+ 'samplesAndGroupsTable.search.placeholder': 'Buscar por muestra',
+ // 22.StatisticalValidationResultBestFeatures.tsx
+ 'statValidationBestFeatures.series.coefficient': 'Coeficiente',
+ 'statValidationBestFeatures.axis.molecule': 'Molécula',
+ 'statValidationBestFeatures.axis.coefficient': 'Coeficiente',
+ 'statValidationBestFeatures.noData': 'No se encontraron características significativas para esta validación estadística',
+ // 23.StatisticalValidationResultKaplanMeier.tsx
+ 'kaplanMeier.axis.time': 'Tiempo',
+ 'kaplanMeier.axis.probability': 'Probabilidad',
+ 'kaplanMeier.info.coxRegression': 'Estas métricas se calculan usando Cox-Regression',
+ 'kaplanMeier.header.clusteringMetrics': 'Métricas de clustering',
+ 'kaplanMeier.button.clusteringModel': 'Modelo de clustering',
+ 'kaplanMeier.button.groupByClinical': 'Agrupar por atributo clínico',
+ 'kaplanMeier.select.clinicalAttribute': 'Atributo clínico para agrupar',
+ 'kaplanMeier.metric.cIndex': 'Índice C',
+ 'kaplanMeier.metric.partialLogLikelihood': 'Log-verosimilitud parcial',
+ 'kaplanMeier.button.seeSamplesAndClusters': 'Ver muestras y clusters',
+ 'kaplanMeier.modal.samplesAndClusters': 'Muestras y clusters',
+ // 24.StatisticalValidationResultMetrics.tsx
+ 'statValidationMetrics.header.metrics': 'métricas',
+ 'statValidationMetrics.header.modelDetails': 'Detalles del modelo',
+ 'statValidationMetrics.header.validationMetrics': 'Métricas de validación',
+ 'statValidationMetrics.metric.mse': 'MSE',
+ 'statValidationMetrics.metric.r2Score': 'Puntaje R2',
+ // 25.NewStatisticalValidationModal.tsx
+ 'newStatValidation.header.create': 'Crear nueva validación estadística',
+ 'newStatValidation.header.basicData': 'Datos básicos',
+ 'newStatValidation.form.name': 'Nombre',
+ 'newStatValidation.form.descriptionOptional': 'Descripción (opcional)',
+ 'newStatValidation.form.requiredField': 'Campo obligatorio',
+ 'newStatValidation.step.trainedModel': 'Paso 1: Modelo entrenado',
+ 'newStatValidation.step.validationDatasets': 'Paso 2: Conjuntos de validación',
+ 'newStatValidation.button.continue': 'Continuar',
+ 'newStatValidation.button.confirm': 'Confirmar',
+ // 26.StatisticalValidationMenu.tsx
+ 'statValidationMenu.bestFeatures': 'Características más significativas',
+ 'statValidationMenu.bestFeatures.info': 'Características más significativas para el análisis de supervivencia',
+ 'statValidationMenu.kaplanMeier': 'Kaplan-Meier',
+ 'statValidationMenu.kaplanMeier.info': 'Curva Kaplan-Meier mostrando supervivencia o hazard ratio',
+ 'statValidationMenu.heatmap': 'Mapa de calor',
+ 'statValidationMenu.heatmap.info': 'Mapa de calor para cada muestra y molécula',
+ // 27.StatisticalValidationsTable.tsx
+ 'statValidationsTable.stopValidation.header': 'Detener validación estadística',
+ 'statValidationsTable.stopValidation.confirm': '¿Está seguro de que desea detener la validación estadística {name}?',
+ 'statValidationsTable.deleteValidation.header': 'Eliminar validación estadística',
+ 'statValidationsTable.deleteValidation.confirm': '¿Está seguro de que desea eliminar la validación estadística {name}?',
+ 'statValidationsTable.headerTitle': 'Validaciones estadísticas',
+ 'statValidationsTable.headers.name': 'Nombre',
+ 'statValidationsTable.headers.description': 'Descripción',
+ 'statValidationsTable.headers.state': 'Estado',
+ 'statValidationsTable.headers.model': 'Modelo',
+ 'statValidationsTable.headers.date': 'Fecha',
+ 'statValidationsTable.headers.datasets': 'Conjuntos de datos',
+ 'statValidationsTable.headers.actions': 'Acciones',
+ 'statValidationsTable.search.label': 'Nombre',
+ 'statValidationsTable.search.placeholder': 'Buscar por nombre o descripción',
+ 'statValidationsTable.newValidation': 'Nueva validación estadística',
+ 'statValidationsTable.actions.seeResults': 'Ver resultados',
+ 'statValidationsTable.actions.stopValidation': 'Detener validación estadística',
+ 'statValidationsTable.actions.deleteValidation': 'Eliminar validación estadística',
+ // 28.NewClusteringModelForm.tsx
+ 'newClusteringForm.label.algorithm': 'Algoritmo',
+ 'newClusteringForm.placeholder.algorithm': 'Seleccione un algoritmo',
+ 'newClusteringForm.label.searchOptimalClusters': 'Buscar el número óptimo de clusters',
+ 'newClusteringForm.label.nClusters': 'Número de clusters',
+ 'newClusteringForm.info.nClusters': 'Número de clusters para agrupar los datos. El número óptimo puede encontrarse buscando el codo en la curva de la suma de distancias cuadradas entre muestras y su centro de cluster más cercano.',
+ 'newClusteringForm.label.metric': 'Métrica',
+ 'newClusteringForm.placeholder.metric': 'Seleccione una métrica',
+ 'newClusteringForm.label.scoringMethod': 'Método de puntuación',
+ 'newClusteringForm.placeholder.scoringMethod': 'Seleccione un método',
+ 'newClusteringForm.label.randomState': 'Semilla aleatoria',
+ 'newClusteringForm.label.penalizer': 'Penalizador',
+ 'newClusteringForm.placeholder.integer': 'Un número entero',
+ 'newClusteringForm.info.algorithm': 'K-Means: agrupa datos minimizando la varianza intra-cluster; útil para RNA y miRNA. Spectral Clustering: usa similitud basada en grafos para patrones complejos; ideal para metilación y CNA. BK-Means: variación jerárquica de K-Means, adecuada para datasets clínicos y multi-ómicos. Método de Ward: minimiza la varianza en clustering jerárquico; útil para combinar RNA y metilación.',
+ 'newClusteringForm.info.metric': 'Cox Regression: modelo de riesgos proporcionales para asociaciones entre multi-ómicos y resultados clínicos. Log-Rank Test: prueba no paramétrica para comparar distribuciones de supervivencia; actualmente no disponible.',
+ 'newClusteringForm.info.scoringMethod': 'C-Index: medida de concordancia entre resultados predichos y observados; valores altos indican mejor desempeño. Log Likelihood: probabilidad de observar los datos dado el modelo; valores bajos indican mejor desempeño.',
+ 'newClusteringForm.info.randomState': 'Semilla usada por el generador aleatorio para asegurar reproducibilidad.',
+ 'newClusteringForm.info.penalizer': 'Útil cuando hay pocas muestras o eventos observados; aumenta la robustez del modelo evitando problemas con valores NaN.',
+}
From 3a7303e1e55bc00c0109d2a25d1095dd5fbb3444 Mon Sep 17 00:00:00 2001
From: natharisa
Date: Fri, 16 Jan 2026 11:39:14 -0300
Subject: [PATCH 06/11] translation updates
---
.../src/components/about-us/AboutUs.tsx | 10 +--
.../inference/InferenceExperimentsTable.tsx | 8 +--
.../inference/NewInferenceExperimentModal.tsx | 6 +-
.../SamplesAndGroupsInferenceTable.tsx | 8 +--
.../SamplesAndTimeInferenceTable.tsx | 6 +-
.../molecules/MoleculesDetailsMenu.tsx | 2 +-
.../molecules/MoleculesTable.tsx | 6 +-
.../GeneOntologyCytoscapeChart.tsx | 2 +-
.../molecules/genes/GeneInformation.tsx | 8 +--
.../molecules/genes/MetabolicPathways.tsx | 2 +-
.../molecules/genes/PathwaysInformation.tsx | 4 +-
.../methylation/MethylationInformation.tsx | 2 +-
.../NewStatisticalValidationModal.tsx | 4 +-
.../StatisticalValidationsTable.tsx | 10 +--
.../result/SamplesAndGroupsTable.tsx | 6 +-
...tatisticalValidationResultBestFeatures.tsx | 2 +-
.../StatisticalValidationResultMetrics.tsx | 2 +-
.../trained-models/NewRFModelForm.tsx | 6 +-
.../static/frontend/src/locales/en.ts | 62 ++++++-------------
.../static/frontend/src/locales/es.ts | 57 ++++++-----------
20 files changed, 87 insertions(+), 126 deletions(-)
diff --git a/src/frontend/static/frontend/src/components/about-us/AboutUs.tsx b/src/frontend/static/frontend/src/components/about-us/AboutUs.tsx
index 6440da30..c978f099 100644
--- a/src/frontend/static/frontend/src/components/about-us/AboutUs.tsx
+++ b/src/frontend/static/frontend/src/components/about-us/AboutUs.tsx
@@ -57,8 +57,8 @@ export const AboutUs = () => {
-
-
+
+
@@ -70,14 +70,16 @@ export const AboutUs = () => {
{intl.formatMessage({ id: 'about.members.title' })}
+
- {intl.formatMessage({ id: 'about.members.main' })}
+ {intl.formatMessage({ id: 'about.members.main' })} B.Comp.Sc. Genaro Camele
- {intl.formatMessage({ id: 'about.members.collaborators' })}
+ {intl.formatMessage({ id: 'about.members.collaborators' })} Esp. Hernán Chanfreau, Dr. Sebastián Menazzi, St. Agustín Marraco, B.Comp.Sc. Julián Muhlberger, St. Ramiro Lasorsa, PhD. Waldo Hasperué
+
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentsTable.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentsTable.tsx
index 946309b0..9d581863 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentsTable.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentsTable.tsx
@@ -169,19 +169,19 @@ export const InferenceExperimentsTable = (props: InferenceExperimentsTableProps)
headerTitle={intl.formatMessage({ id: 'inference.experiments.table.title' })}
headers={[
- { name: intl.formatMessage({ id: 'inference.table.columns.name' }), serverCodeToSort: 'name', width: 3 },
- { name: intl.formatMessage({ id: 'inference.table.columns.description' }), serverCodeToSort: 'description', width: 4 },
+ { name: intl.formatMessage({ id: 'common.name' }), serverCodeToSort: 'name', width: 3 },
+ { name: intl.formatMessage({ id: 'common.description' }), serverCodeToSort: 'description', width: 4 },
{ name: intl.formatMessage({ id: 'inference.table.columns.state' }), serverCodeToSort: 'state', textAlign: 'center' },
{ name: intl.formatMessage({ id: 'inference.table.columns.model' }), serverCodeToSort: 'model', width: 1 },
{ name: intl.formatMessage({ id: 'inference.table.columns.date' }), serverCodeToSort: 'created' },
{ name: intl.formatMessage({ id: 'inference.table.columns.dataset' }) },
- { name: intl.formatMessage({ id: 'inference.table.columns.actions' }) }
+ { name: intl.formatMessage({ id: 'common.actions' }) }
]}
queryParams={{ biomarker_pk: props.selectedBiomarker.id }}
defaultSortProp={{ sortField: 'created', sortOrderAscendant: false }}
showSearchInput
- searchLabel={intl.formatMessage({ id: 'inference.search.label' })}
+ searchLabel={intl.formatMessage({ id: 'common.name' })}
searchPlaceholder={intl.formatMessage({ id: 'inference.search.placeholder' })}
urlToRetrieveData={urlBiomarkerInferenceExperiments}
customElements={[
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/NewInferenceExperimentModal.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/NewInferenceExperimentModal.tsx
index 61aaac85..1ff3afb7 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/NewInferenceExperimentModal.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/NewInferenceExperimentModal.tsx
@@ -322,7 +322,7 @@ export const NewInferenceExperimentModal = (props: NewInferenceExperimentModalPr
name='name'
value={form.name}
icon='asterisk'
- placeholder={intl.formatMessage({ id: 'inference.new.name' })}
+ placeholder={intl.formatMessage({ id: 'common.name' })}
onChange={handleInputChange}
/>
@@ -383,7 +383,7 @@ export const NewInferenceExperimentModal = (props: NewInferenceExperimentModalPr
color='red'
onClick={() => setCurrentStep(currentStep - 1)}
>
- {intl.formatMessage({ id: 'inference.new.goBack' })}
+ {intl.formatMessage({ id: 'common.goBack' })}
)}
@@ -411,7 +411,7 @@ export const NewInferenceExperimentModal = (props: NewInferenceExperimentModalPr
}}
disabled={!formIsValid()}
>
- {intl.formatMessage({ id: 'inference.new.confirm' })}
+ {intl.formatMessage({ id: 'common.confirm' })}
)}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndGroupsInferenceTable.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndGroupsInferenceTable.tsx
index 47a3937c..d915da4e 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndGroupsInferenceTable.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndGroupsInferenceTable.tsx
@@ -49,7 +49,7 @@ export const SamplesAndGroupsInferenceTable = (props: SamplesAndGroupsInferenceT
headers={[
- { name: intl.formatMessage({ id: 'inference.table.columns.sample' }), serverCodeToSort: 'sample', width: 3, textAlign: 'center' },
+ { name: intl.formatMessage({ id: 'common.sample' }), serverCodeToSort: 'sample', width: 3, textAlign: 'center' },
{ name: intl.formatMessage({ id: 'inference.table.columns.cluster' }), serverCodeToSort: 'cluster', width: 2, textAlign: 'center' }
]}
@@ -66,7 +66,7 @@ export const SamplesAndGroupsInferenceTable = (props: SamplesAndGroupsInferenceT
]}
customFilters={[
{
- label: intl.formatMessage({ id: 'inference.table.filter.cluster.label' }),
+ label: intl.formatMessage({ id: 'common.sample' }),
keyForServer: 'cluster',
defaultValue: '',
placeholder: intl.formatMessage({ id: 'inference.table.filter.cluster.placeholder' }),
@@ -77,8 +77,8 @@ export const SamplesAndGroupsInferenceTable = (props: SamplesAndGroupsInferenceT
defaultSortProp={{ sortField: 'sample', sortOrderAscendant: false }}
showSearchInput
defaultPageSize={25}
- searchLabel={intl.formatMessage({ id: 'inference.table.search.label' })}
- searchPlaceholder={intl.formatMessage({ id: 'inference.table.search.placeholder' })}
+ searchLabel={intl.formatMessage({ id: 'common.sample' })}
+ searchPlaceholder={intl.formatMessage({ id: 'common.search' })}
urlToRetrieveData={urlInferenceExperimentSamplesAndClusters}
mapFunction={(sampleAndCluster: SampleAndCluster) => {
return (
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndTimeInferenceTable.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndTimeInferenceTable.tsx
index d47aa937..32956d34 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndTimeInferenceTable.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndTimeInferenceTable.tsx
@@ -50,7 +50,7 @@ export const SamplesAndTimeInferenceTable = (props: SamplesAndTimeInferenceTable
return (
headers={[
- { name: intl.formatMessage({ id: 'inference.timeTable.columns.sample' }), serverCodeToSort: 'sample', width: 3, textAlign: 'center' },
+ { name: intl.formatMessage({ id: 'common.sample' }), serverCodeToSort: 'sample', width: 3, textAlign: 'center' },
{ name: intl.formatMessage({ id: 'inference.timeTable.columns.predictedTime' }), serverCodeToSort: 'prediction', width: 2, textAlign: 'center' }
]}
@@ -70,8 +70,8 @@ export const SamplesAndTimeInferenceTable = (props: SamplesAndTimeInferenceTable
defaultSortProp={{ sortField: 'sample', sortOrderAscendant: false }}
showSearchInput
defaultPageSize={25}
- searchLabel={intl.formatMessage({ id: 'inference.timeTable.search.label' })}
- searchPlaceholder={intl.formatMessage({ id: 'inference.timeTable.search.placeholder' })}
+ searchLabel={intl.formatMessage({ id: 'common.sample' })}
+ searchPlaceholder={intl.formatMessage({ id: 'common.search' })}
searchWidth={5}
entriesSelectWidth={3}
urlToRetrieveData={urlInferenceExperimentSamplesAndTime}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/MoleculesDetailsMenu.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/MoleculesDetailsMenu.tsx
index ea118238..d41a8bfe 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/MoleculesDetailsMenu.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/MoleculesDetailsMenu.tsx
@@ -36,7 +36,7 @@ export const MoleculesDetailsMenu = (props: MoleculesDetailsMenuProps) => {
*/
const items: ItemMenuProp[] = [
{
- name: intl.formatMessage({ id: 'moleculesDetailsMenu.details' }),
+ name: intl.formatMessage({ id: 'common.details' }),
onClick: () => props.setActiveItem(ActiveBiomarkerMoleculeItemMenu.DETAILS),
isActive: props.activeItem === ActiveBiomarkerMoleculeItemMenu.DETAILS,
popupInfo: `Details of ${props.selectedMolecule.identifier} obtained from different standardized sources`,
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/MoleculesTable.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/MoleculesTable.tsx
index b58bb72e..e19784ab 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/MoleculesTable.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/MoleculesTable.tsx
@@ -46,8 +46,8 @@ export const MoleculesTable = (props: MoleculesTableProps) => {
defaultSortProp={{ sortField: 'identifier', sortOrderAscendant: true }}
showSearchInput
defaultPageSize={25}
- searchLabel={intl.formatMessage({ id: 'moleculesTable.search.label' })}
- searchPlaceholder={intl.formatMessage({ id: 'moleculesTable.search.placeholder' })}
+ searchLabel={intl.formatMessage({ id: 'common.sample' })}
+ searchPlaceholder={intl.formatMessage({ id: 'common.search' }) + ' ' + intl.formatMessage({ id: 'moleculesTable.header.identifier' })}
urlToRetrieveData={urlBiomarkerMolecules}
searchWidth={6}
entriesSelectWidth={3}
@@ -62,7 +62,7 @@ export const MoleculesTable = (props: MoleculesTableProps) => {
name='chart bar'
className='clickable'
color='blue'
- title={intl.formatMessage({ id: 'moleculesTable.details' })}
+ title={intl.formatMessage({ id: 'common.details' })}
onClick={() => props.openMoleculeDetails(molecule)}
/>
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/gene-ontology/GeneOntologyCytoscapeChart.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/gene-ontology/GeneOntologyCytoscapeChart.tsx
index d1c94702..429c6a37 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/gene-ontology/GeneOntologyCytoscapeChart.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/gene-ontology/GeneOntologyCytoscapeChart.tsx
@@ -199,7 +199,7 @@ export const GeneOntologyCytoscapeChart = (props: GeneOntologyCytoscapeChartProp
{/* Go back button. */}
-
+
{/* Form for termsRelatedToTermForm */}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/NewStatisticalValidationModal.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/NewStatisticalValidationModal.tsx
index ebd9abf9..151a0b5c 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/NewStatisticalValidationModal.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/NewStatisticalValidationModal.tsx
@@ -327,7 +327,7 @@ export const NewStatisticalValidationModal = (props: NewStatisticalValidationMod
name='name'
value={form.name}
icon='asterisk'
- placeholder={intl.formatMessage({ id: 'newStatValidation.form.name' })}
+ placeholder={intl.formatMessage({ id: 'common.name' })}
onChange={handleInputChange}
/>
@@ -415,7 +415,7 @@ export const NewStatisticalValidationModal = (props: NewStatisticalValidationMod
}}
disabled={!formIsValid()}
>
- {intl.formatMessage({ id: 'newStatValidation.button.confirm' })}
+ {intl.formatMessage({ id: 'common.confirm' })}
)}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/StatisticalValidationsTable.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/StatisticalValidationsTable.tsx
index 4513af9a..03b9f5b5 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/StatisticalValidationsTable.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/StatisticalValidationsTable.tsx
@@ -171,19 +171,19 @@ export const StatisticalValidationsTable = (props: StatisticalValidationsTablePr
headerTitle={intl.formatMessage({ id: 'statValidationsTable.headerTitle' })}
headers={[
- { name: intl.formatMessage({ id: 'statValidationsTable.headers.name' }), serverCodeToSort: 'name', width: 3 },
- { name: intl.formatMessage({ id: 'statValidationsTable.headers.description' }), serverCodeToSort: 'description', width: 4 },
+ { name: intl.formatMessage({ id: 'common.name' }), serverCodeToSort: 'name', width: 3 },
+ { name: intl.formatMessage({ id: 'common.description' }), serverCodeToSort: 'description', width: 4 },
{ name: intl.formatMessage({ id: 'statValidationsTable.headers.state' }), serverCodeToSort: 'state', textAlign: 'center' },
{ name: intl.formatMessage({ id: 'statValidationsTable.headers.model' }), textAlign: 'center', width: 2 },
{ name: intl.formatMessage({ id: 'statValidationsTable.headers.date' }), serverCodeToSort: 'created' },
{ name: intl.formatMessage({ id: 'statValidationsTable.headers.datasets' }) },
- { name: 'Actions' }
+ { name: intl.formatMessage({ id: 'common.actions' }) }
]}
queryParams={{ biomarker_pk: props.selectedBiomarker.id }}
defaultSortProp={{ sortField: 'created', sortOrderAscendant: false }}
showSearchInput
- searchLabel={intl.formatMessage({ id: 'statValidationsTable.search.label' })}
- searchPlaceholder={intl.formatMessage({ id: 'statValidationsTable.search.placeholder' })}
+ searchLabel={intl.formatMessage({ id: 'common.name' })}
+ searchPlaceholder={intl.formatMessage({ id: 'common.search' }) + ' ' + intl.formatMessage({ id: 'common.name' }) + ' / ' + intl.formatMessage({ id: 'common.description' })}
urlToRetrieveData={urlBiomarkerStatisticalValidations}
customElements={[
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/SamplesAndGroupsTable.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/SamplesAndGroupsTable.tsx
index 4b370bd6..8499bf5b 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/SamplesAndGroupsTable.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/SamplesAndGroupsTable.tsx
@@ -24,7 +24,7 @@ export const SamplesAndGroupsTable = (props: SamplesAndGroupsTableProps) => {
return (
headers={[
- { name: intl.formatMessage({ id: 'samplesAndGroupsTable.header.sample' }), serverCodeToSort: 'sample', width: 3 },
+ { name: intl.formatMessage({ id: 'common.sample' }), serverCodeToSort: 'sample', width: 3 },
{ name: intl.formatMessage({ id: 'samplesAndGroupsTable.header.cluster' }), serverCodeToSort: 'cluster', width: 2 }
]}
queryParams={{ statistical_validation_pk: props.selectedStatisticalValidation.id }}
@@ -41,8 +41,8 @@ export const SamplesAndGroupsTable = (props: SamplesAndGroupsTableProps) => {
defaultSortProp={{ sortField: 'sample', sortOrderAscendant: false }}
showSearchInput
defaultPageSize={25}
- searchLabel={intl.formatMessage({ id: 'samplesAndGroupsTable.search.label' })}
- searchPlaceholder={intl.formatMessage({ id: 'samplesAndGroupsTable.search.placeholder' })}
+ searchLabel={intl.formatMessage({ id: 'common.sample' })}
+ searchPlaceholder={intl.formatMessage({ id: 'common.search' }) + ' ' + intl.formatMessage({ id: 'common.sample' })}
urlToRetrieveData={urlStatisticalValidationSamplesAndClusters}
mapFunction={(sampleAndCluster: SampleAndCluster) => {
return (
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/StatisticalValidationResultBestFeatures.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/StatisticalValidationResultBestFeatures.tsx
index ff1ded6d..bcb00df3 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/StatisticalValidationResultBestFeatures.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/StatisticalValidationResultBestFeatures.tsx
@@ -136,7 +136,7 @@ export const StatisticalValidationResultBestFeatures = (props: StatisticalValida
max: Math.ceil(Math.max(...coefficients) + EPSILON)
},
noData: {
- text: intl.formatMessage({ id: 'statValidationBestFeatures.noData' })
+ text: intl.formatMessage({ id: 'common.noDetails' }) + ' ' + intl.formatMessage({ id: 'statValidationBestFeatures.context.features' })
}
}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/StatisticalValidationResultMetrics.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/StatisticalValidationResultMetrics.tsx
index a69fb325..a73067fd 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/StatisticalValidationResultMetrics.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/StatisticalValidationResultMetrics.tsx
@@ -79,7 +79,7 @@ export const StatisticalValidationResultMetrics = (props: StatisticalValidationR
{/* Model details. */}
- {intl.formatMessage({ id: 'statValidationMetrics.header.modelDetails' })}
+ {intl.formatMessage({ id: 'common.details' }) + ' ' + intl.formatMessage({ id: 'statValidationMetrics.header.model' })}
{props.selectedStatisticalValidation.trained_model !== null &&
}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/trained-models/NewRFModelForm.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/trained-models/NewRFModelForm.tsx
index 4b3b09b6..c159e00c 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/trained-models/NewRFModelForm.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/trained-models/NewRFModelForm.tsx
@@ -3,6 +3,7 @@ import { Form, InputOnChangeData } from 'semantic-ui-react'
import { RFParameters } from '../../types'
import { InfoPopup } from '../../../pipeline/experiment-result/gene-gem-details/InfoPopup'
import { InputLabel } from '../../../common/InputLabel'
+import { useIntl } from 'react-intl'
interface NewSVMModelFormProps {
/** Getter of the selected params to handle in the form. */
@@ -14,6 +15,7 @@ interface NewSVMModelFormProps {
}
export const NewRFModelForm = (props: NewSVMModelFormProps) => {
+ const intl = useIntl()
// TODO: add an InfoPopup for all the inputs
const lookForOptimalNEstimators = props.parameters.lookForOptimalNEstimators
return (
@@ -40,9 +42,9 @@ export const NewRFModelForm = (props: NewSVMModelFormProps) => {
+
Date: Fri, 23 Jan 2026 10:21:28 -0300
Subject: [PATCH 07/11] Translation updates
---
.../InferenceExperimentResultMetrics.tsx | 2 +-
.../inference/NewInferenceExperimentModal.tsx | 2 +-
.../NewStatisticalValidationModal.tsx | 2 +-
.../StatisticalValidationMenu.tsx | 2 +-
.../trained-models/NewClusteringModelForm.tsx | 4 ++--
.../trained-models/NewRFModelForm.tsx | 20 ++++++++--------
.../trained-models/NewSVMModelForm.tsx | 20 +++++++++-------
.../static/frontend/src/locales/en.ts | 23 +++++++++++++++---
.../static/frontend/src/locales/es.ts | 24 +++++++++++++++----
9 files changed, 67 insertions(+), 32 deletions(-)
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentResultMetrics.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentResultMetrics.tsx
index 2d74c9bf..60a3a157 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentResultMetrics.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentResultMetrics.tsx
@@ -27,7 +27,7 @@ export const InferenceExperimentResultMetrics = (props: InferenceExperimentResul
{/* Model details. */}
- {intl.formatMessage({ id: 'inference.model.details' })}
+ {intl.formatMessage({ id: 'common.details' }) + ' ' + intl.formatMessage({ id: 'inference.model' })}
{props.selectedInferenceExperiment.trained_model !== null &&
}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/NewInferenceExperimentModal.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/NewInferenceExperimentModal.tsx
index 1ff3afb7..aea77731 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/NewInferenceExperimentModal.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/NewInferenceExperimentModal.tsx
@@ -335,7 +335,7 @@ export const NewInferenceExperimentModal = (props: NewInferenceExperimentModalPr
- {intl.formatMessage({ id: 'inference.new.requiredField' })}
+ {intl.formatMessage({ id: 'common.requiredField' })}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/NewStatisticalValidationModal.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/NewStatisticalValidationModal.tsx
index 151a0b5c..3f196522 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/NewStatisticalValidationModal.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/NewStatisticalValidationModal.tsx
@@ -340,7 +340,7 @@ export const NewStatisticalValidationModal = (props: NewStatisticalValidationMod
- {intl.formatMessage({ id: 'newStatValidation.form.requiredField' })}
+ {intl.formatMessage({ id: 'common.requiredField' })}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/StatisticalValidationMenu.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/StatisticalValidationMenu.tsx
index 38c15668..2d94acf6 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/StatisticalValidationMenu.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/StatisticalValidationMenu.tsx
@@ -41,7 +41,7 @@ export const StatisticalValidationMenu = (props: StatisticalValidationMenuProps)
active={props.activeItem === ActiveStatValidationsItemMenu.KAPLAN_MEIER}
onClick={() => props.setActiveItem(ActiveStatValidationsItemMenu.KAPLAN_MEIER)}
>
- {intl.formatMessage({ id: 'statValidationMenu.kaplanMeier' })}
+ Kaplan-Meier
{
+
{
checked={lookForOptimalNEstimators}
onChange={(_e, { checked }) => { props.handleChangeOptimalNEstimators(checked ?? false) }}
label={(
-
+
{
+
{
+
{
/>
)}
- placeholder='An integer number'
+ placeholder={intl.formatMessage({ id: 'common.integerNumber' })}
type='number'
min={3}
name='maxDepth'
@@ -87,9 +87,9 @@ export const NewRFModelForm = (props: NewSVMModelFormProps) => {
+
{
/>
)}
- placeholder='An integer number'
+ placeholder={intl.formatMessage({ id: 'common.integerNumber' })}
type='number'
step={1}
min={0}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/trained-models/NewSVMModelForm.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/trained-models/NewSVMModelForm.tsx
index 050f2e2e..877ea0e6 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/trained-models/NewSVMModelForm.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/trained-models/NewSVMModelForm.tsx
@@ -4,6 +4,7 @@ import { SVMKernelOptions } from '../../utils'
import { SVMParameters } from '../../types'
import { InfoPopup } from '../../../pipeline/experiment-result/gene-gem-details/InfoPopup'
import { InputLabel } from '../../../common/InputLabel'
+import { useIntl } from 'react-intl'
interface NewSVMModelFormProps {
/** Getter of the selected params to handle in the form. */
@@ -13,6 +14,7 @@ interface NewSVMModelFormProps {
}
export const NewSVMModelForm = (props: NewSVMModelFormProps) => {
+ const intl = useIntl()
return (
<>
{
- Linear Kernel: Best for linearly separable data; commonly used for simple genomic or clinical feature classification.
- Polynomial Kernel: Captures non-linear patterns; effective for complex relationships in multi-omics data.
- RBF Kernel: Maps data to a higher-dimensional space; ideal for handling non-linear separations in RNA and methylation analyses.
+ {intl.formatMessage({ id: 'newSVMForm.info.kernel.linear' })}
+ {intl.formatMessage({ id: 'newSVMForm.info.kernel.polynomial' })}
+ {intl.formatMessage({ id: 'newSVMForm.info.kernel.rbf' })}
>
)}
onTop={false}
@@ -36,7 +38,7 @@ export const NewSVMModelForm = (props: NewSVMModelFormProps) => {
)}
options={SVMKernelOptions}
- placeholder='Select a kernel'
+ placeholder={intl.formatMessage({ id: 'newSVMForm.placeholder.kernel' })}
name='kernel'
value={props.parameters.kernel}
onChange={props.handleChangeParams}
@@ -46,9 +48,9 @@ export const NewSVMModelForm = (props: NewSVMModelFormProps) => {
+
{
+
{
/>
)}
- placeholder='An integer number'
+ placeholder={intl.formatMessage({ id: 'common.integerNumber' })}
type='number'
step={1}
min={0}
diff --git a/src/frontend/static/frontend/src/locales/en.ts b/src/frontend/static/frontend/src/locales/en.ts
index 6a5fc4ef..8a263c57 100644
--- a/src/frontend/static/frontend/src/locales/en.ts
+++ b/src/frontend/static/frontend/src/locales/en.ts
@@ -88,7 +88,6 @@ export default {
'inference.new.description': 'Description (optional)',
'inference.newInference.title': 'Create new inference experiment',
'inference.new.basicData': 'Basic data',
- 'inference.new.requiredField': 'Required field',
'inference.new.step1': 'Step 1: Trained model',
'inference.new.step2': 'Step 2: molecules datasets',
'inference.new.continue': 'Continue',
@@ -231,7 +230,6 @@ export default {
'newStatValidation.header.create': 'Create new statistical validation',
'newStatValidation.header.basicData': 'Basic data',
'newStatValidation.form.descriptionOptional': 'Description (optional)',
- 'newStatValidation.form.requiredField': 'Required field',
'newStatValidation.step.trainedModel': 'Step 1: Trained model',
'newStatValidation.step.validationDatasets': 'Step 2: Validation datasets',
'newStatValidation.button.continue': 'Continue',
@@ -239,7 +237,7 @@ export default {
'statValidationMenu.bestFeatures': 'Most significant features',
'statValidationMenu.bestFeatures.info': 'Most significant features for the survival analysis',
'statValidationMenu.kaplanMeier': 'Kaplan-Meier',
- 'statValidationMenu.kaplanMeier.info': 'Kaplan-Meier curve showing survival or hazard ratio',
+ 'statValidationMenu.kaplanMeier.info': 'curve showing survival or hazard ratio',
'statValidationMenu.heatmap': 'Heatmap',
'statValidationMenu.heatmap.info': 'Heatmap for every sample and molecule',
// 27.StatisticalValidationsTable.tsx
@@ -276,4 +274,23 @@ export default {
'newClusteringForm.info.scoringMethod': 'C-Index: A measure of concordance between predicted and observed survival outcomes; higher values indicate better performance. Log Likelihood: The probability of observing the data given the model; lower values indicate better performance.',
'newClusteringForm.info.randomState': 'The seed used by the random number generator to ensure reproducibility.',
'newClusteringForm.info.penalizer': 'Useful when clinical data has few samples or events; increases robustness and avoids NaN values.',
+ // 29.NewRFModelForm.tsx
+ 'newRFForm.label.searchOptimalTrees': 'Search for the optimal number of trees',
+ 'newRFForm.info.searchOptimalTrees': 'This option is useful when the number of samples in the clinical data is small or there are few observed events; setting this value increases the robustness of the model in such cases, avoiding problems with NaN values.',
+ 'newRFForm.label.maxDepth': 'Max depth',
+ 'newRFForm.info.maxDepth': 'The maximum depth of the tree',
+ 'newRFForm.label.randomState': 'Random state',
+ 'newRFForm.info.randomState': 'Seed used by the random number generator',
+ 'newRFForm.label.nEstimators': 'Number of trees',
+ 'newRFForm.info.nEstimators': 'The number of trees (estimators) used in the Random Forest model.',
+ // 30.NewSVMModelForm.tsx
+ 'newSVMForm.info.kernel.linear': 'Linear Kernel: Best for linearly separable data; commonly used for simple genomic or clinical feature classification.',
+ 'newSVMForm.info.kernel.polynomial': 'Polynomial Kernel: Captures non-linear patterns; effective for complex relationships in multi-omics data.',
+ 'newSVMForm.info.kernel.rbf': 'RBF Kernel: Maps data to a higher-dimensional space; ideal for handling non-linear separations in RNA and methylation analyses.',
+ 'newSVMForm.placeholder.kernel': 'Select a kernel',
+ 'newSVMForm.label.maxIterations': 'Max iterations',
+ 'newSVMForm.info.maxIterations': 'The maximum number of iterations to be run',
+ 'newSVMForm.label.randomState': 'Random state',
+ 'newSVMForm.info.randomState': 'Seed used by the random number generator',
+
}
diff --git a/src/frontend/static/frontend/src/locales/es.ts b/src/frontend/static/frontend/src/locales/es.ts
index 7f483694..77497c91 100644
--- a/src/frontend/static/frontend/src/locales/es.ts
+++ b/src/frontend/static/frontend/src/locales/es.ts
@@ -90,7 +90,6 @@ export default {
'inference.new.description': 'Descripción (opcional)',
'inference.newInference.title': 'Crear nuevo experimento de inferencia',
'inference.new.basicData': 'Datos básicos',
- 'inference.new.requiredField': 'Campo obligatorio',
'inference.new.step1': 'Paso 1: Modelo entrenado',
'inference.new.step2': 'Paso 2: Conjuntos de datos de moléculas',
'inference.new.continue': 'Continuar',
@@ -237,15 +236,13 @@ export default {
'newStatValidation.header.create': 'Crear nueva validación estadística',
'newStatValidation.header.basicData': 'Datos básicos',
'newStatValidation.form.descriptionOptional': 'Descripción (opcional)',
- 'newStatValidation.form.requiredField': 'Campo obligatorio',
'newStatValidation.step.trainedModel': 'Paso 1: Modelo entrenado',
'newStatValidation.step.validationDatasets': 'Paso 2: Conjuntos de validación',
'newStatValidation.button.continue': 'Continuar',
// 26.StatisticalValidationMenu.tsx
'statValidationMenu.bestFeatures': 'Características más significativas',
'statValidationMenu.bestFeatures.info': 'Características más significativas para el análisis de supervivencia',
- 'statValidationMenu.kaplanMeier': 'Kaplan-Meier',
- 'statValidationMenu.kaplanMeier.info': 'Curva Kaplan-Meier mostrando supervivencia o hazard ratio',
+ 'statValidationMenu.kaplanMeier.info': 'Curva mostrando supervivencia o hazard ratio',
'statValidationMenu.heatmap': 'Mapa de calor',
'statValidationMenu.heatmap.info': 'Mapa de calor para cada muestra y molécula',
// 27.StatisticalValidationsTable.tsx
@@ -281,4 +278,23 @@ export default {
'newClusteringForm.info.scoringMethod': 'C-Index: medida de concordancia entre resultados predichos y observados; valores altos indican mejor desempeño. Log Likelihood: probabilidad de observar los datos dado el modelo; valores bajos indican mejor desempeño.',
'newClusteringForm.info.randomState': 'Semilla usada por el generador aleatorio para asegurar reproducibilidad.',
'newClusteringForm.info.penalizer': 'Útil cuando hay pocas muestras o eventos observados; aumenta la robustez del modelo evitando problemas con valores NaN.',
+ // 29.NewRFModelForm.tsx
+ 'newRFForm.label.searchOptimalTrees': 'Buscar el número óptimo de árboles',
+ 'newRFForm.info.searchOptimalTrees': 'Esta opción es útil cuando el número de muestras en los datos clínicos es pequeño o hay pocos eventos observados; establecer este valor aumenta la robustez del modelo en tales casos, evitando problemas con valores NaN.',
+ 'newRFForm.label.maxDepth': 'Profundidad máxima',
+ 'newRFForm.info.maxDepth': 'La profundidad máxima del árbol',
+ 'newRFForm.label.randomState': 'Estado aleatorio',
+ 'newRFForm.info.randomState': 'Semilla utilizada por el generador de números aleatorios',
+ 'newRFForm.label.nEstimators': 'Número de árboles',
+ 'newRFForm.info.nEstimators': 'El número de árboles (estimadores) utilizados en el modelo Random Forest.',
+ // 30.NewSVMModelForm.tsx
+ 'newSVMForm.info.kernel.linear': 'Kernel lineal: Mejor para datos linealmente separables; comúnmente usado para clasificación simple de características genómicas o clínicas.',
+ 'newSVMForm.info.kernel.polynomial': 'Kernel polinomial: Captura patrones no lineales; efectivo para relaciones complejas en datos multi-ómicos.',
+ 'newSVMForm.info.kernel.rbf': 'Kernel RBF: Mapea los datos a un espacio de mayor dimensión; ideal para manejar separaciones no lineales en análisis de ARN y metilación.',
+ 'newSVMForm.placeholder.kernel': 'Seleccionar un kernel',
+ 'newSVMForm.label.maxIterations': 'Iteraciones máximas',
+ 'newSVMForm.info.maxIterations': 'El número máximo de iteraciones a ejecutar',
+ 'newSVMForm.label.randomState': 'Estado aleatorio',
+ 'newSVMForm.info.randomState': 'Semilla utilizada por el generador de números aleatorios',
+
}
From cc3bf8a48688bdd740646760bbef0d420c9ed350 Mon Sep 17 00:00:00 2001
From: natharisa
Date: Fri, 20 Feb 2026 10:20:03 -0300
Subject: [PATCH 08/11] Translation updates
---
.../BiomarkerTrainedModelsTable.tsx | 60 ++++----
.../ModelDetailsPanels.tsx | 23 +--
.../trained-models/NewTrainedModelModal.tsx | 34 +++--
.../biomarkers/labels/BiomarkerStateLabel.tsx | 29 ++--
.../biomarkers/labels/SVMKernelTask.tsx | 6 +-
.../labels/TrainedModelStateLabel.tsx | 44 ++++--
.../BiomarkerTypeSelection.tsx | 15 +-
.../CrossValidationInput.tsx | 37 +++--
.../steps/FeatureSelectionForm.tsx | 11 +-
.../steps/FeatureSelectionStep1.tsx | 8 +-
.../steps/FeatureSelectionStep3.tsx | 12 +-
.../steps/advancedMode/BBHAAdvanced.tsx | 43 +++---
.../advancedMode/CoxRegressionAdvanced.tsx | 8 +-
.../steps/advancedMode/GAAdvanced.tsx | 27 ++--
.../steps/algorithms/ClusteringPanel.tsx | 11 +-
.../steps/algorithms/RFPanel.tsx | 8 +-
.../steps/algorithms/SVMPanel.tsx | 4 +-
.../static/frontend/src/locales/en.ts | 141 ++++++++++++++++++
.../static/frontend/src/locales/es.ts | 141 ++++++++++++++++++
19 files changed, 511 insertions(+), 151 deletions(-)
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/BiomarkerTrainedModelsTable.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/BiomarkerTrainedModelsTable.tsx
index 07b80220..4d877e70 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/BiomarkerTrainedModelsTable.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/BiomarkerTrainedModelsTable.tsx
@@ -13,6 +13,7 @@ import ky from 'ky'
import { StopExperimentButton } from '../../pipeline/all-experiments-view/StopExperimentButton'
import { DeleteButton } from '../../common/DeleteButton'
import { TableCellSources } from '../../common/TableCellSources'
+import { useIntl } from 'react-intl'
declare const urlBiomarkerTrainedModels: string
declare const urlStopTrainedModel: string
@@ -37,6 +38,7 @@ interface BiomarkerTrainedModelsPanelProps {
* @returns Component.
*/
export const BiomarkerTrainedModelsTable = (props: BiomarkerTrainedModelsPanelProps) => {
+ const intl = useIntl()
const [showNewTrainedModelModal, setShowNewTrainedModelModal] = useState(false)
const [stoppingTrainedModel, setStoppingTrainedModel] = useState(false)
@@ -117,13 +119,16 @@ export const BiomarkerTrainedModelsTable = (props: BiomarkerTrainedModelsPanelPr
return (
-
+
- Are you sure you want to stop the training of model {trainedModelToStop.name} ?
+ {intl.formatMessage(
+ { id: 'biomarkerTrainedModelsTable.confirm.stopTraining' },
+ { modelName: trainedModelToStop.name }
+ )}
- Cancel
+ {intl.formatMessage({ id: 'common.cancel' })}
- Stop
+ {intl.formatMessage({ id: 'biomarkerTrainedModelsTable.button.stop' })}
@@ -149,16 +154,20 @@ export const BiomarkerTrainedModelsTable = (props: BiomarkerTrainedModelsPanelPr
return (
-
+
- Are you sure you want to delete the Biomarker {trainedModelToRemove.name} ?
+ {intl.formatMessage(
+ { id: 'biomarkerTrainedModelsTable.confirm.deleteBiomarker' },
+ { modelName: trainedModelToRemove.name }
+ )}
+
- Cancel
+ {intl.formatMessage({ id: 'common.cancel' })}
- Delete
+ {intl.formatMessage({ id: 'common.delete' })}
@@ -205,26 +214,27 @@ export const BiomarkerTrainedModelsTable = (props: BiomarkerTrainedModelsPanelPr
{/* TrainedModels table. */}
- headerTitle='Trained models'
+ headerTitle={intl.formatMessage({ id: 'biomarkerTrainedModelsTable.header.trainedModels' })}
headers={[
- { name: 'Name', serverCodeToSort: 'name', width: 3 },
- { name: 'Description', serverCodeToSort: 'description', width: 4 },
- { name: 'State', serverCodeToSort: 'state', width: 1 },
- { name: 'Model', serverCodeToSort: 'fitness_function', width: 1 },
- { name: 'Date', serverCodeToSort: 'created' },
- { name: 'Metric', serverCodeToSort: 'fitness_metric' },
- { name: 'Best CV metric', serverCodeToSort: 'best_fitness_value' },
- { name: 'Datasets' },
+ { name: intl.formatMessage({ id: 'common.name' }), serverCodeToSort: 'name', width: 3 },
+ { name: intl.formatMessage({ id: 'common.description' }), serverCodeToSort: 'description', width: 4 },
+ { name: intl.formatMessage({ id: 'biomarkerTrainedModelsTable.header.state' }), serverCodeToSort: 'state', width: 1 },
+ { name: intl.formatMessage({ id: 'biomarkerTrainedModelsTable.header.model' }), serverCodeToSort: 'fitness_function', width: 1 },
+ { name: intl.formatMessage({ id: 'biomarkerTrainedModelsTable.header.date' }), serverCodeToSort: 'created' },
+ { name: intl.formatMessage({ id: 'biomarkerTrainedModelsTable.header.metric' }), serverCodeToSort: 'fitness_metric' },
+ { name: intl.formatMessage({ id: 'biomarkerTrainedModelsTable.header.bestCVMetric' }), serverCodeToSort: 'best_fitness_value' },
+ { name: intl.formatMessage({ id: 'biomarkerTrainedModelsTable.header.datasets' }) },
...actionColumn
+
]}
defaultSortProp={{ sortField: 'created', sortOrderAscendant: false }}
queryParams={{ biomarker_pk: props.selectedBiomarker.id, ...extraQueryParams }}
customFilters={[
{
- label: 'Model type',
+ label: intl.formatMessage({ id: 'biomarkerTrainedModelsTable.filter.modelType' }),
keyForServer: 'fitness_function',
defaultValue: '',
- placeholder: 'Model type',
+ placeholder: intl.formatMessage({ id: 'biomarkerTrainedModelsTable.filter.modelType' }),
options: fitnessFunctionsOptions,
width: 3
},
@@ -233,7 +243,7 @@ export const BiomarkerTrainedModelsTable = (props: BiomarkerTrainedModelsPanelPr
customElements={
props.allowFullManagement
? [
-
+
{ setShowNewTrainedModelModal(true) }}>
@@ -242,8 +252,8 @@ export const BiomarkerTrainedModelsTable = (props: BiomarkerTrainedModelsPanelPr
: undefined
}
showSearchInput
- searchLabel='Name'
- searchPlaceholder='Search by name or description'
+ searchLabel={intl.formatMessage({ id: 'common.name' })}
+ searchPlaceholder={intl.formatMessage({ id: 'biomarkerTrainedModelsTable.search.placeholder' })}
searchWidth={4}
entriesSelectWidth={2}
urlToRetrieveData={urlBiomarkerTrainedModels}
@@ -289,7 +299,7 @@ export const BiomarkerTrainedModelsTable = (props: BiomarkerTrainedModelsPanelPr
{/* Stop button */}
{isInProcess && (
setTrainedModelToStop(trainedModel)}
/>
)}
@@ -300,8 +310,8 @@ export const BiomarkerTrainedModelsTable = (props: BiomarkerTrainedModelsPanelPr
setTrainedModelToRemove(trainedModel)}
ownerId={null}
/>
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/ModelDetailsPanels.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/ModelDetailsPanels.tsx
index 7a977f52..7a3a4c08 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/ModelDetailsPanels.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/ModelDetailsPanels.tsx
@@ -9,6 +9,7 @@ import { FitnessFunction, ClusteringModelDetails, SVMModelDetails, ModelDetails,
import { Nullable } from '../../../utils/interfaces'
import ky from 'ky'
import { alertGeneralError } from '../../../utils/util_functions'
+import { useIntl } from 'react-intl'
declare const urlStatisticalValidationModalDetails: string
@@ -21,13 +22,14 @@ type GeneralMetricsProps = { data: ModelDetails, fitness_function: FitnessFuncti
* @returns Component.
*/
const GeneralMetrics = (props: GeneralMetricsProps) => {
+ const intl = useIntl()
return (
<>
- Model:
+ {intl.formatMessage({ id: 'common.model' })}
{
- Best fitness value: {props.data.best_fitness.toFixed(4)}
+ {intl.formatMessage({ id: 'modelDetails.general.bestFitnessValue' })} {props.data.best_fitness.toFixed(4)}
@@ -49,7 +51,7 @@ const GeneralMetrics = (props: GeneralMetricsProps) => {
- Random state: {props.data.random_state ?? '-'}
+ {intl.formatMessage({ id: 'modelDetails.general.randomState' })} {props.data.random_state ?? '-'}
@@ -66,6 +68,7 @@ type ClusteringModelDetailsPanelProps = { data: ClusteringModelDetails, fitness_
* @returns Component.
*/
const ClusteringModelDetailsPanel = (props: ClusteringModelDetailsPanelProps) => {
+ const intl = useIntl()
return (
@@ -74,7 +77,7 @@ const ClusteringModelDetailsPanel = (props: ClusteringModelDetailsPanelProps) =>
- Algorithm:
+ {intl.formatMessage({ id: 'modelDetails.clustering.algorithm' })}
@@ -84,7 +87,7 @@ const ClusteringModelDetailsPanel = (props: ClusteringModelDetailsPanelProps) =>
- Scoring method:
+ {intl.formatMessage({ id: 'modelDetails.clustering.scoringMethod' })}
@@ -93,7 +96,7 @@ const ClusteringModelDetailsPanel = (props: ClusteringModelDetailsPanelProps) =>
- Number of clusters: {props.data.n_clusters}
+ {intl.formatMessage({ id: 'modelDetails.clustering.numberOfClusters' })} {props.data.n_clusters}
@@ -109,6 +112,7 @@ type SVMModelDetailsPanelProps = { data: SVMModelDetails, fitness_function: Fitn
* @returns Component.
*/
const SVMModelDetailsPanel = (props: SVMModelDetailsPanelProps) => {
+ const intl = useIntl()
return (
@@ -127,7 +131,7 @@ const SVMModelDetailsPanel = (props: SVMModelDetailsPanelProps) => {
- Task:
+ {intl.formatMessage({ id: 'modelDetails.svm.task' })}
@@ -146,6 +150,7 @@ type RFModelDetailsPanelProps = { data: RFModelDetails, fitness_function: Fitnes
* @returns Component.
*/
const RFModelDetailsPanel = (props: RFModelDetailsPanelProps) => {
+ const intl = useIntl()
return (
@@ -153,13 +158,13 @@ const RFModelDetailsPanel = (props: RFModelDetailsPanelProps) => {
- Number of estimators: {props.data.n_estimators}
+ {intl.formatMessage({ id: 'modelDetails.rf.numberOfEstimators' })} {props.data.n_estimators}
- Max. depth: {props.data.max_depth ?? '-'}
+ {intl.formatMessage({ id: 'modelDetails.rf.maxDepth' })} {props.data.max_depth ?? '-'}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/trained-models/NewTrainedModelModal.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/trained-models/NewTrainedModelModal.tsx
index 41de0e9c..aaa23a93 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/trained-models/NewTrainedModelModal.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/trained-models/NewTrainedModelModal.tsx
@@ -12,7 +12,7 @@ import { NewClusteringModelForm } from './NewClusteringModelForm'
import { NewRFModelForm } from './NewRFModelForm'
import { InfoPopup } from '../../../pipeline/experiment-result/gene-gem-details/InfoPopup'
import { InputLabel } from '../../../common/InputLabel'
-
+import { useIntl } from 'react-intl'
declare const urlNewTrainedModel: string
/** NewTrainedModelModal props. */
@@ -79,6 +79,7 @@ const getDefaultNewTrainedModelData = (): NewTrainedModelData => ({
* @returns Component.
*/
export const NewTrainedModelModal = (props: NewTrainedModelModalProps) => {
+ const intl = useIntl()
const [form, setForm] = useState(getDefaultNewTrainedModelData())
const [currentStep, setCurrentStep] = useState<1 | 2>(1)
const [sendingData, setSendingData] = useState(false)
@@ -409,7 +410,7 @@ export const NewTrainedModelModal = (props: NewTrainedModelModalProps) => {
- Select a new model to train
+ {intl.formatMessage({ id: 'newTrainedModelModal.header.selectModel' })}
{
{/* Specific model params */}
{selectedFitnessFunction !== null &&
- }
+ {intl.formatMessage({ id: 'newTrainedModelModal.header.selectModelParameters' })} }
- Required field
+ {intl.formatMessage({ id: 'common.requiredField' })}
@@ -552,7 +553,7 @@ export const NewTrainedModelModal = (props: NewTrainedModelModalProps) => {
1} link onClick={() => { setCurrentStep(1) }}>
- Step 1: Training parameters
+ {intl.formatMessage({ id: 'newTrainedModelModal.step1.trainingParameters' })}
{
>
- Step 2: Training datasets
+ {intl.formatMessage({ id: 'newTrainedModelModal.step2.trainingDatasets' })}
@@ -582,7 +583,7 @@ export const NewTrainedModelModal = (props: NewTrainedModelModalProps) => {
- props.setShowNewTrainedModelModal(false)}>Cancel
+ props.setShowNewTrainedModelModal(false)}>{intl.formatMessage({ id: 'common.cancel' })}
{/* Submit StatisticalAnalysis button */}
{
}}
disabled={isLastStep ? !formIsValid() : !modelIsValid}
>
- {isLastStep ? 'Confirm' : 'Continue'}
+ {isLastStep ? intl.formatMessage({ id: 'common.confirm' }) : intl.formatMessage({ id: 'newTrainedModelModal.button.continue' })}
+
diff --git a/src/frontend/static/frontend/src/components/biomarkers/labels/BiomarkerStateLabel.tsx b/src/frontend/static/frontend/src/components/biomarkers/labels/BiomarkerStateLabel.tsx
index 84bc037d..5d0e27e7 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/labels/BiomarkerStateLabel.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/labels/BiomarkerStateLabel.tsx
@@ -2,6 +2,7 @@ import React from 'react'
import { Icon } from 'semantic-ui-react'
import { StateIconInfo } from '../../../utils/interfaces'
import { BiomarkerState } from '../types'
+import { useIntl } from 'react-intl'
/** BiomarkerStateLabel props. */
interface BiomarkerStateLabelProps {
@@ -15,6 +16,7 @@ interface BiomarkerStateLabelProps {
* @returns Component.
*/
export const BiomarkerStateLabel = (props: BiomarkerStateLabelProps) => {
+ const intl = useIntl()
let stateIcon: StateIconInfo
switch (props.biomarkerState) {
@@ -23,7 +25,7 @@ export const BiomarkerStateLabel = (props: BiomarkerStateLabelProps) => {
iconName: 'check',
color: 'green',
loading: false,
- title: 'The experiment is complete'
+ title: intl.formatMessage({ id: 'biomarkerState.completed' })
}
break
case BiomarkerState.FINISHED_WITH_ERROR:
@@ -31,7 +33,7 @@ export const BiomarkerStateLabel = (props: BiomarkerStateLabelProps) => {
iconName: 'times',
color: 'red',
loading: false,
- title: 'The experiment has finished with errors. Try again'
+ title: intl.formatMessage({ id: 'biomarkerState.finishedWithError' })
}
break
case BiomarkerState.WAITING_FOR_QUEUE:
@@ -39,7 +41,8 @@ export const BiomarkerStateLabel = (props: BiomarkerStateLabelProps) => {
iconName: 'wait',
color: 'yellow',
loading: false,
- title: 'The process of this experiment will start soon'
+ title: intl.formatMessage({ id: 'biomarkerState.waitingForQueue' })
+
}
break
case BiomarkerState.NO_SAMPLES_IN_COMMON:
@@ -47,7 +50,7 @@ export const BiomarkerStateLabel = (props: BiomarkerStateLabelProps) => {
iconName: 'user outline',
color: 'red',
loading: false,
- title: 'Datasets don\'t have samples in common'
+ title: intl.formatMessage({ id: 'biomarkerState.noSamplesInCommon' })
}
break
case BiomarkerState.IN_PROCESS:
@@ -55,14 +58,14 @@ export const BiomarkerStateLabel = (props: BiomarkerStateLabelProps) => {
iconName: 'sync alternate',
color: 'yellow',
loading: true,
- title: 'The experiment is being processed'
+ title: intl.formatMessage({ id: 'biomarkerState.inProcess' })
}
break
case BiomarkerState.STOPPING:
stateIcon = {
iconName: 'stop',
loading: false,
- title: 'The experiment is being stopped',
+ title: intl.formatMessage({ id: 'biomarkerState.stopping' }),
className: 'experiment-stopping-icon'
}
break
@@ -71,7 +74,7 @@ export const BiomarkerStateLabel = (props: BiomarkerStateLabelProps) => {
iconName: 'stop',
color: 'red',
loading: false,
- title: 'The experiment was stopped'
+ title: intl.formatMessage({ id: 'biomarkerState.stopped' })
}
break
case BiomarkerState.REACHED_ATTEMPTS_LIMIT:
@@ -79,7 +82,7 @@ export const BiomarkerStateLabel = (props: BiomarkerStateLabelProps) => {
iconName: 'undo',
color: 'red',
loading: false,
- title: 'The experiment has failed several times. Try changing some parameters and try again'
+ title: intl.formatMessage({ id: 'biomarkerState.reachedAttemptsLimit' })
}
break
case BiomarkerState.NO_FEATURES_FOUND:
@@ -87,7 +90,7 @@ export const BiomarkerStateLabel = (props: BiomarkerStateLabelProps) => {
iconName: 'times rectangle',
color: 'red',
loading: false,
- title: 'No features were found. Try changing some parameters and try again'
+ title: intl.formatMessage({ id: 'biomarkerState.noFeaturesFound' })
}
break
case BiomarkerState.EMPTY_DATASET:
@@ -95,7 +98,7 @@ export const BiomarkerStateLabel = (props: BiomarkerStateLabelProps) => {
iconName: 'user times',
color: 'red',
loading: false,
- title: 'After filtering out invalid values such as NaN or inf, there were no molecules or samples to make inference. Perhaps the requested molecules do not exist in the dataset, or all patients contain NaN or inf data. Try changing the dataset used or correct your data and try again.'
+ title: intl.formatMessage({ id: 'biomarkerState.emptyDataset' })
}
break
case BiomarkerState.NO_VALID_MOLECULES:
@@ -103,7 +106,7 @@ export const BiomarkerStateLabel = (props: BiomarkerStateLabelProps) => {
iconName: 'browser',
color: 'red',
loading: false,
- title: 'The dataset used has not enough molecules to compute the experiment (i.e.: has different molecules than the specified in the Biomarker). Select other dataset and try again'
+ title: intl.formatMessage({ id: 'biomarkerState.noValidMolecules' })
}
break
case BiomarkerState.NUMBER_OF_SAMPLES_FEWER_THAN_CV_FOLDS:
@@ -111,7 +114,7 @@ export const BiomarkerStateLabel = (props: BiomarkerStateLabelProps) => {
iconName: 'user times',
color: 'red',
loading: false,
- title: 'There is a less number of members of each class than the number of CrossValidation folds. We tried to set a lower split number but it still failed. Try selecting a larger dataset and try again'
+ title: intl.formatMessage({ id: 'biomarkerState.numberOfSamplesFewerThanCvFolds' })
}
break
case BiomarkerState.TIMEOUT_EXCEEDED:
@@ -119,7 +122,7 @@ export const BiomarkerStateLabel = (props: BiomarkerStateLabelProps) => {
iconName: 'wait',
color: 'red',
loading: false,
- title: 'The analysis has reached the timeout limit. Try changing some parameters and try again'
+ title: intl.formatMessage({ id: 'biomarkerState.timeoutExceeded' })
}
break
}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/labels/SVMKernelTask.tsx b/src/frontend/static/frontend/src/components/biomarkers/labels/SVMKernelTask.tsx
index d057d8d3..dc48b2b2 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/labels/SVMKernelTask.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/labels/SVMKernelTask.tsx
@@ -1,6 +1,7 @@
import React from 'react'
import { Label, SemanticCOLORS } from 'semantic-ui-react'
import { SVMTask } from '../types'
+import { useIntl } from 'react-intl'
/** SVMKernelTask props. */
interface SVMKernelTaskProps {
@@ -16,17 +17,18 @@ interface SVMKernelTaskProps {
* @returns Component.
*/
export const SVMKernelTask = (props: SVMKernelTaskProps) => {
+ const intl = useIntl()
let color: SemanticCOLORS
let description: string
switch (props.task) {
case SVMTask.REGRESSION:
color = 'green'
- description = 'Regression'
+ description = intl.formatMessage({ id: 'svmTask.regression' })
break
case SVMTask.RANKING:
color = 'blue'
- description = 'Ranking'
+ description = intl.formatMessage({ id: 'svmTask.ranking' })
break
default:
color = 'blue'
diff --git a/src/frontend/static/frontend/src/components/biomarkers/labels/TrainedModelStateLabel.tsx b/src/frontend/static/frontend/src/components/biomarkers/labels/TrainedModelStateLabel.tsx
index f6e78007..148c92fd 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/labels/TrainedModelStateLabel.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/labels/TrainedModelStateLabel.tsx
@@ -2,6 +2,7 @@ import React from 'react'
import { Icon } from 'semantic-ui-react'
import { StateIconInfo } from '../../../utils/interfaces'
import { TrainedModelState } from '../types'
+import { useIntl } from 'react-intl'
/** TrainedModelStateLabel props. */
interface TrainedModelStateLabelProps {
@@ -17,6 +18,7 @@ interface TrainedModelStateLabelProps {
* @returns Component.
*/
export const TrainedModelStateLabel = (props: TrainedModelStateLabelProps) => {
+ const intl = useIntl()
let stateIcon: StateIconInfo
switch (props.trainedModelStateState) {
@@ -25,7 +27,11 @@ export const TrainedModelStateLabel = (props: TrainedModelStateLabelProps) => {
iconName: 'check',
color: props.cvFoldsWereModified ? 'orange' : 'green',
loading: false,
- title: 'The experiment is complete' + (props.cvFoldsWereModified ? ' (number of CrossValidation folds were modified to be stratified)' : '')
+ title: intl.formatMessage(
+ { id: 'trainedModelState.completed' },
+ { cvModified: props.cvFoldsWereModified }
+ )
+
}
break
case TrainedModelState.FINISHED_WITH_ERROR:
@@ -33,7 +39,7 @@ export const TrainedModelStateLabel = (props: TrainedModelStateLabelProps) => {
iconName: 'times',
color: 'red',
loading: false,
- title: 'The experiment has finished with errors. Try again'
+ title: intl.formatMessage({ id: 'trainedModelState.finishedWithError' })
}
break
case TrainedModelState.WAITING_FOR_QUEUE:
@@ -41,7 +47,8 @@ export const TrainedModelStateLabel = (props: TrainedModelStateLabelProps) => {
iconName: 'wait',
color: 'yellow',
loading: false,
- title: 'The process of this experiment will start soon'
+ title: intl.formatMessage({ id: 'trainedModelState.waitingForQueue' })
+
}
break
case TrainedModelState.NO_SAMPLES_IN_COMMON:
@@ -49,7 +56,8 @@ export const TrainedModelStateLabel = (props: TrainedModelStateLabelProps) => {
iconName: 'user outline',
color: 'red',
loading: false,
- title: 'Datasets don\'t have samples in common'
+ title: intl.formatMessage({ id: 'trainedModelState.noSamplesInCommon' })
+
}
break
case TrainedModelState.IN_PROCESS:
@@ -57,14 +65,15 @@ export const TrainedModelStateLabel = (props: TrainedModelStateLabelProps) => {
iconName: 'sync alternate',
color: 'yellow',
loading: true,
- title: 'The experiment is being processed'
+ title: intl.formatMessage({ id: 'trainedModelState.inProcess' })
+
}
break
case TrainedModelState.STOPPING:
stateIcon = {
iconName: 'stop',
loading: false,
- title: 'The experiment is being stopped',
+ title: intl.formatMessage({ id: 'trainedModelState.stopping' }),
className: 'experiment-stopping-icon'
}
break
@@ -73,7 +82,8 @@ export const TrainedModelStateLabel = (props: TrainedModelStateLabelProps) => {
iconName: 'stop',
color: 'red',
loading: false,
- title: 'The experiment was stopped'
+ title: intl.formatMessage({ id: 'trainedModelState.stopped' })
+
}
break
case TrainedModelState.REACHED_ATTEMPTS_LIMIT:
@@ -81,7 +91,8 @@ export const TrainedModelStateLabel = (props: TrainedModelStateLabelProps) => {
iconName: 'undo',
color: 'red',
loading: false,
- title: 'The experiment has failed several times. Try changing some parameters and try again'
+ title: intl.formatMessage({ id: 'trainedModelState.reachedAttemptsLimit' })
+
}
break
case TrainedModelState.NO_FEATURES_FOUND:
@@ -89,7 +100,8 @@ export const TrainedModelStateLabel = (props: TrainedModelStateLabelProps) => {
iconName: 'times rectangle',
color: 'red',
loading: false,
- title: 'No features were found. Try changing some parameters and try again'
+ title: intl.formatMessage({ id: 'trainedModelState.noFeaturesFound' })
+
}
break
case TrainedModelState.NO_BEST_MODEL_FOUND:
@@ -97,7 +109,8 @@ export const TrainedModelStateLabel = (props: TrainedModelStateLabelProps) => {
iconName: 'target',
color: 'red',
loading: false,
- title: 'No model could be obtained. Maybe there are fewer samples than number of folds in the CrossValidation or the data presents high collinearity. Try changing some parameters as penalizer or number of folds in the CV process and try again'
+ title: intl.formatMessage({ id: 'trainedModelState.noBestModelFound' })
+
}
break
case TrainedModelState.NUMBER_OF_SAMPLES_FEWER_THAN_CV_FOLDS:
@@ -105,7 +118,7 @@ export const TrainedModelStateLabel = (props: TrainedModelStateLabelProps) => {
iconName: 'user times',
color: 'red',
loading: false,
- title: 'There is a less number of members of each class than the number of CrossValidation folds. We tried to set a lower split number but it still failed. Try selecting a larger dataset and try again'
+ title: intl.formatMessage({ id: 'trainedModelState.numberOfSamplesFewerThanCvFolds' })
}
break
case TrainedModelState.MODEL_DUMP_NOT_AVAILABLE:
@@ -113,7 +126,8 @@ export const TrainedModelStateLabel = (props: TrainedModelStateLabelProps) => {
iconName: 'target',
color: 'orange',
loading: false,
- title: 'The Feature Selection process has finished correctly, but there was a problem obtaining the model. Try training a new model'
+ title: intl.formatMessage({ id: 'trainedModelState.modelDumpNotAvailable' })
+
}
break
case TrainedModelState.TIMEOUT_EXCEEDED:
@@ -121,7 +135,8 @@ export const TrainedModelStateLabel = (props: TrainedModelStateLabelProps) => {
iconName: 'wait',
color: 'red',
loading: false,
- title: 'The training process has reached the timeout limit. Try changing some parameters and try again'
+ title: intl.formatMessage({ id: 'trainedModelState.timeoutExceeded' })
+
}
break
case TrainedModelState.EMPTY_DATASET:
@@ -129,7 +144,8 @@ export const TrainedModelStateLabel = (props: TrainedModelStateLabelProps) => {
iconName: 'user times',
color: 'red',
loading: false,
- title: 'After filtering out invalid values such as NaN or inf, there were no molecules or samples to train the model. Perhaps the requested molecules do not exist in the dataset, or all patients contain NaN or inf data. Try changing the dataset used or correct your data and try again.'
+ title: intl.formatMessage({ id: 'trainedModelState.emptyDataset' })
+
}
break
}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/biomarkerTypeSelection/BiomarkerTypeSelection.tsx b/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/biomarkerTypeSelection/BiomarkerTypeSelection.tsx
index 88e6f6ff..ed4f9994 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/biomarkerTypeSelection/BiomarkerTypeSelection.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/biomarkerTypeSelection/BiomarkerTypeSelection.tsx
@@ -1,6 +1,7 @@
import React from 'react'
import { Card, Grid, Header, Image } from 'semantic-ui-react'
import { BiomarkerOrigin } from '../../types'
+import { useIntl } from 'react-intl'
/** BiomarkerTypeSelection props. */
interface BiomarkerTypeSelectionProps {
@@ -8,16 +9,17 @@ interface BiomarkerTypeSelectionProps {
}
export const BiomarkerTypeSelection = (props: BiomarkerTypeSelectionProps) => {
+ const intl = useIntl()
const cards = [
{
- title: 'Emtpy',
- description: 'Create an empty Biomarker. You can later add molecules or features (genes, microRNAs, DNA methylation, CNAs) that will make up the biomarker',
+ title: intl.formatMessage({ id: 'biomarkerType.empty.title' }),
+ description: intl.formatMessage({ id: 'biomarkerType.empty.description' }),
action: () => props.handleSelectModal(BiomarkerOrigin.MANUAL),
image: '/static/frontend/img/biomarkers/Empty.png'
},
{
- title: 'Feature Selection/ML',
- description: 'As a starting point, you can select a previously discovered Biomarker, a well-known Biomarker, or a superset of genes that you would like to test. This method will select the molecular subset that fits the better prediction',
+ title: intl.formatMessage({ id: 'biomarkerType.featureSelection.title' }),
+ description: intl.formatMessage({ id: 'biomarkerType.featureSelection.description' }),
action: () => props.handleSelectModal(BiomarkerOrigin.FEATURE_SELECTION),
image: '/static/frontend/img/biomarkers/Fs3.png'
}
@@ -25,13 +27,14 @@ export const BiomarkerTypeSelection = (props: BiomarkerTypeSelectionProps) => {
return (
<>
- Create a new Biomarker
+ {intl.formatMessage({ id: 'biomarkerType.createNew' })}
+
- Choose type of Biomarker
+ {intl.formatMessage({ id: 'biomarkerType.chooseType' })}
{
cards.map(card => (
diff --git a/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/CrossValidationInput.tsx b/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/CrossValidationInput.tsx
index cda33116..125fe9f6 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/CrossValidationInput.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/CrossValidationInput.tsx
@@ -1,5 +1,6 @@
import React from 'react'
import { Form } from 'semantic-ui-react'
+import { useIntl } from 'react-intl'
/** CrossValidationInput props. */
interface CrossValidationInputProps {
@@ -14,18 +15,24 @@ interface CrossValidationInputProps {
* @param props Component props.
* @returns Component.
*/
-export const CrossValidationInput = (props: CrossValidationInputProps) => (
- { props.handleChange(name, value as any) }}
- />
-)
+export const CrossValidationInput = (props: CrossValidationInputProps) => {
+ const intl = useIntl()
+
+ return (
+ {
+ props.handleChange(name, value as any)
+ }}
+ />
+ )
+}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/FeatureSelectionForm.tsx b/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/FeatureSelectionForm.tsx
index 74283e4c..eb22b0cb 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/FeatureSelectionForm.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/FeatureSelectionForm.tsx
@@ -7,6 +7,7 @@ import { fitnessFunctionsOptions } from '../../../utils'
import { RFPanel } from './algorithms/RFPanel'
import { RandomStateInput } from '../RandomStateInput'
import { CrossValidationInput } from '../CrossValidationInput'
+import { useIntl } from 'react-intl'
/** FeatureSelectionForm props. */
interface FeatureSelectionFormProps {
@@ -35,6 +36,8 @@ export const FeatureSelectionForm = (props: FeatureSelectionFormProps) => {
isExpertOn
} = props
+ const intl = useIntl()
+
/**
* Returns the panel with the options of the selected fitness function.
* @returns Component.
@@ -51,7 +54,7 @@ export const FeatureSelectionForm = (props: FeatureSelectionFormProps) => {
- Search for the optimal number of clusters (soon)
+ {intl.formatMessage({ id: 'featureSelection.searchOptimalClusters' })}
{
fluid
style={{ minWidth: '180px', maxWidth: '100% ' }}
type='number'
- label='Number of clusters'
+ label={intl.formatMessage({ id: 'featureSelection.numberOfClusters' })}
name='nClusters'
min={2}
max={10}
@@ -89,7 +92,7 @@ export const FeatureSelectionForm = (props: FeatureSelectionFormProps) => {
fluid
style={{ minWidth: '180px', maxWidth: '100% ' }}
type='number'
- label='Penalizer'
+ label={intl.formatMessage({ id: 'featureSelection.penalizer' })}
name='penalizer'
min={0}
value={fitnessFunctionParameters.clusteringParameters.penalizer}
@@ -118,7 +121,7 @@ export const FeatureSelectionForm = (props: FeatureSelectionFormProps) => {
{
markBiomarkerAsSelected,
handleCompleteStep1
} = props
+ const intl = useIntl()
return (
- headerTitle='Biomarkers'
+ headerTitle={intl.formatMessage({ id: 'featureSelectionStep1.headerTitle' })}
headers={defaultHeaders}
customFilters={customFilters}
queryParams={{
@@ -38,8 +40,8 @@ export const FeatureSelectionStep1 = (props: FeatureSelectionStep1Props) => {
}}
defaultSortProp={{ sortField: 'upload_date', sortOrderAscendant: false }}
showSearchInput
- searchLabel='Name'
- searchPlaceholder='Search by name'
+ searchLabel={intl.formatMessage({ id: 'common.name' })}
+ searchPlaceholder={intl.formatMessage({ id: 'featureSelectionStep1.searchPlaceholder' })}
urlToRetrieveData={urlBiomarkersCRUD}
updateWSKey='update_biomarkers'
mapFunction={(biomarker: Biomarker) => (
diff --git a/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/FeatureSelectionStep3.tsx b/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/FeatureSelectionStep3.tsx
index 9f88047b..f7ab0ce5 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/FeatureSelectionStep3.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/FeatureSelectionStep3.tsx
@@ -6,6 +6,7 @@ import { BBHAAdvanced } from './advancedMode/BBHAAdvanced'
import { CoxRegressionAdvanced } from './advancedMode/CoxRegressionAdvanced'
import { getNumberOfMoleculesOfBiomarker } from '../../../utils'
import { GAAdvanced } from './advancedMode/GAAdvanced'
+import { useIntl } from 'react-intl'
declare const maxFeaturesBlindSearch: number
declare const minFeaturesMetaheuristics: number
@@ -31,6 +32,7 @@ export const FeatureSelectionStep3 = (props: FeatureSelectionStep3Props) => {
handleChangeAdvanceAlgorithm,
handleSwitchAdvanceAlgorithm
} = props
+ const intl = useIntl()
const numberOfMolecules = useMemo(
() => getNumberOfMoleculesOfBiomarker(props.featureSelection.selectedBiomarker),
@@ -135,21 +137,21 @@ export const FeatureSelectionStep3 = (props: FeatureSelectionStep3Props) => {
{
onClick={() => handleSwitchAdvanceAlgorithm()}
className='selection-step-button-advance-mode'
>
- Expert mode
+ {intl.formatMessage({ id: 'featureSelectionStep3.expertMode' })}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/advancedMode/BBHAAdvanced.tsx b/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/advancedMode/BBHAAdvanced.tsx
index c7cb645a..dea2417e 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/advancedMode/BBHAAdvanced.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/advancedMode/BBHAAdvanced.tsx
@@ -4,6 +4,7 @@ import { InfoPopup } from '../../../../../pipeline/experiment-result/gene-gem-de
import { advanceBBHAOptions, improvedBBHACoeff1Options, improvedBBHACoeff2Options } from '../../../../utils'
import { AdvancedBBHA, BBHAVersion } from '../../../../types'
import { ExternalLink } from '../../../../../common/ExternalLink'
+import { useIntl } from 'react-intl'
declare const sparkIntegrationIsEnabled: boolean
declare const minIterationsMetaheuristics: number
@@ -21,12 +22,17 @@ interface BBHAAdvancedProps {
* Simple component for explanation over coeff1 and coeff2 parameters
* @returns Component.
*/
-const CoeffExplanation = () => (
-
- Coefficient specified in the
- improved Binary Black Hole Algorithm
-
-)
+const CoeffExplanation = () => {
+ const intl = useIntl()
+ return (
+
+ {intl.formatMessage({ id: 'bbha.coefficientExplanation' })}{' '}
+
+ improved Binary Black Hole Algorithm
+
+
+ )
+}
/**
* Renders a form to set some advanced parameters for the BBHA algorithm.
@@ -34,6 +40,7 @@ const CoeffExplanation = () => (
* @returns Component.
*/
export const BBHAAdvanced = (props: BBHAAdvancedProps) => {
+ const intl = useIntl()
const { advancedData, handleChangeAdvanceAlgorithm } = props
return (
@@ -41,8 +48,8 @@ export const BBHAAdvanced = (props: BBHAAdvancedProps) => {
{
@@ -71,8 +78,8 @@ export const BBHAAdvanced = (props: BBHAAdvancedProps) => {
{
@@ -101,7 +108,7 @@ export const BBHAAdvanced = (props: BBHAAdvancedProps) => {
{
content={(
<>
- The Original approach executes the original Binary Black Hole Algorithm as defined in this article .
+ {intl.formatMessage({ id: 'bbha.version.original' })}{' '}
+ this article .
- Version 2 it is an improved version defined in this newer article
+ {intl.formatMessage({ id: 'bbha.version.v2' })}{' '}
+ newer article
>
)}
@@ -131,7 +140,7 @@ export const BBHAAdvanced = (props: BBHAAdvancedProps) => {
{
{
+ const intl = useIntl()
const {
advanceData,
handleChangeAdvanceAlgorithm
@@ -27,8 +29,8 @@ export const CoxRegressionAdvanced = (props: CoxRegressionAdvancedProps) => {
{
diff --git a/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/advancedMode/GAAdvanced.tsx b/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/advancedMode/GAAdvanced.tsx
index 0724c421..19aecd62 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/advancedMode/GAAdvanced.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/advancedMode/GAAdvanced.tsx
@@ -3,6 +3,7 @@ import { Checkbox, Grid, Input } from 'semantic-ui-react'
import { InfoPopup } from '../../../../../pipeline/experiment-result/gene-gem-details/InfoPopup'
import { AdvancedGA } from '../../../../types'
import { ExternalLink } from '../../../../../common/ExternalLink'
+import { useIntl } from 'react-intl'
declare const sparkIntegrationIsEnabled: boolean
declare const minIterationsMetaheuristics: number
@@ -23,14 +24,16 @@ interface GAAdvancedProps {
*/
export const GAAdvanced = (props: GAAdvancedProps) => {
const { advancedData, handleChangeAdvanceAlgorithm } = props
+ const intl = useIntl()
+
return (
{
@@ -59,8 +62,8 @@ export const GAAdvanced = (props: GAAdvancedProps) => {
{
@@ -88,8 +91,8 @@ export const GAAdvanced = (props: GAAdvancedProps) => {
{
@@ -121,7 +124,7 @@ export const GAAdvanced = (props: GAAdvancedProps) => {
{ handleChangeAdvanceAlgorithm('GA', 'useSpark', checked ?? false) }}
/>
@@ -130,7 +133,9 @@ export const GAAdvanced = (props: GAAdvancedProps) => {
- If this option is enabled, the experiment will be executed (if possible) using Apache Spark to optimize execution times
+ {intl.formatMessage({ id: 'ga.useSpark.info' })}{' '}
+ Apache Spark
+
)}
onTop={false}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/algorithms/ClusteringPanel.tsx b/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/algorithms/ClusteringPanel.tsx
index 861b0633..5ab3d423 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/algorithms/ClusteringPanel.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/algorithms/ClusteringPanel.tsx
@@ -2,6 +2,7 @@ import React from 'react'
import { Button, Form, Label, Segment } from 'semantic-ui-react'
import { ClusteringMetric, ClusteringParameters, ClusteringScoringMethod, FitnessFunctionParameters } from '../../../../types'
import { clusteringAlgorithmOptions } from '../../../../utils'
+import { useIntl } from 'react-intl'
/** ClusteringPanel props. */
interface ClusteringPanelProps {
@@ -15,14 +16,15 @@ interface ClusteringPanelProps {
* @returns Component.
*/
export const ClusteringPanel = (props: ClusteringPanelProps) => {
+ const intl = useIntl()
const { settings, handleChangeFitnessFunctionOption } = props
return (
<>
{
- Metric
+ {intl.formatMessage({ id: 'clustering.metric' })}
+
{
- Scoring method
+ {intl.formatMessage({ id: 'clustering.scoringMethod' })}
{
+ const intl = useIntl()
const {
parameters,
handleChangeFitnessFunctionOption
@@ -23,7 +25,7 @@ export const RFPanel = (props: RFPanelProps) => {
<>
{
{
+ const intl = useIntl()
const {
parameters: svm,
handleChangeFitnessFunctionOption
@@ -45,7 +47,7 @@ export const SVMPanel = (props: SVMPanelProps) => {
Date: Fri, 23 Jan 2026 15:24:13 -0300
Subject: [PATCH 09/11] Update member title for Genaro Camele
---
.../static/frontend/src/components/about-us/AboutUs.tsx | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/frontend/static/frontend/src/components/about-us/AboutUs.tsx b/src/frontend/static/frontend/src/components/about-us/AboutUs.tsx
index c978f099..8c77c8ae 100644
--- a/src/frontend/static/frontend/src/components/about-us/AboutUs.tsx
+++ b/src/frontend/static/frontend/src/components/about-us/AboutUs.tsx
@@ -70,11 +70,10 @@ export const AboutUs = () => {
{intl.formatMessage({ id: 'about.members.title' })}
-
- {intl.formatMessage({ id: 'about.members.main' })} B.Comp.Sc. Genaro Camele
+ {intl.formatMessage({ id: 'about.members.main' })} PhD in Computer Science Genaro Camele
From 8837cc5b63ddc6110d97eeae2e52573a953d92fe Mon Sep 17 00:00:00 2001
From: natharisa
Date: Wed, 25 Mar 2026 14:54:01 -0300
Subject: [PATCH 10/11] Finished faq and translation update
---
.../static/frontend/src/components/Base.tsx | 44 ++-
.../BiomarkerTrainedModelsTable.tsx | 6 +-
.../ModelDetailsPanels.tsx | 8 +-
.../inference/InferenceExperimentsTable.tsx | 4 +-
.../inference/NewInferenceExperimentModal.tsx | 6 +-
.../SamplesAndGroupsInferenceTable.tsx | 2 +-
.../GeneOntologyCytoscapeChart.tsx | 4 +-
.../genes/GeneAssociationsNetworkPanel.tsx | 2 +-
.../NewStatisticalValidationModal.tsx | 6 +-
.../StatisticalValidationsTable.tsx | 4 +-
.../result/SamplesAndGroupsTable.tsx | 4 +-
...tatisticalValidationResultBestFeatures.tsx | 4 +-
.../trained-models/NewClusteringModelForm.tsx | 18 +-
.../trained-models/NewRFModelForm.tsx | 2 +-
.../trained-models/NewSVMModelForm.tsx | 2 +-
.../trained-models/NewTrainedModelModal.tsx | 8 +-
.../CrossValidationInput.tsx | 4 +-
.../FeatureSelectionPanel.tsx | 15 +-
.../steps/FeatureSelectionForm.tsx | 4 +-
.../steps/FeatureSelectionStep3.tsx | 4 +-
.../steps/advancedMode/BBHAAdvanced.tsx | 10 +-
.../advancedMode/CoxRegressionAdvanced.tsx | 2 +-
.../steps/advancedMode/GAAdvanced.tsx | 6 +-
.../steps/algorithms/ClusteringPanel.tsx | 6 +-
.../steps/algorithms/RFPanel.tsx | 2 +-
.../frontend/src/components/faq/FAQ.tsx | 327 +++++++++++++-----
.../components/faq/FAQQuestionAndAnswer.tsx | 9 +-
src/frontend/static/frontend/src/faq.tsx | 2 +
.../static/frontend/src/locales/en.ts | 82 ++---
.../static/frontend/src/locales/es.ts | 81 ++---
30 files changed, 410 insertions(+), 268 deletions(-)
diff --git a/src/frontend/static/frontend/src/components/Base.tsx b/src/frontend/static/frontend/src/components/Base.tsx
index b70f80e2..84425088 100644
--- a/src/frontend/static/frontend/src/components/Base.tsx
+++ b/src/frontend/static/frontend/src/components/Base.tsx
@@ -4,6 +4,26 @@ import ky from 'ky'
import { DjangoUser } from '../utils/django_interfaces'
import { Nullable } from '../utils/interfaces'
import { Footer } from './Footer'
+import { IntlProvider } from 'react-intl'
+
+// Locales
+import es from '../locales/es'
+import en from '../locales/en'
+
+// Common dependencies for all the pages
+import 'fomantic-ui-css/semantic.css'
+import '../css/base.css'
+
+const messages = { en, es }
+
+interface LocaleContextType {
+ locale: 'en' | 'es',
+ setLocale: React.Dispatch>
+}
+const LocaleContext = React.createContext({
+ locale: 'es',
+ setLocale: () => {}
+})
declare const urlCurrentUser: string
@@ -29,6 +49,8 @@ const Base = (props: BaseProps) => {
const abortController = useRef(new AbortController())
const [currentUser, setUser] = useState>(null)
const [isLoadingCurrentUser, setIsLoadingCurrentUser] = useState(true)
+ // State that defines the current language ('es' or 'en') for , used to display the interface in the selected locale
+ const [locale, setLocale] = useState<'en' | 'es'>('es')
/**
* Method which is executed when the component has mounted
@@ -75,17 +97,21 @@ const Base = (props: BaseProps) => {
return (
- {/* Navbar */}
-
+
+
+ {/* Navbar */}
+
- {/* Composition part */}
-
- {props.children}
-
+ {/* Composition part */}
+
+ {props.children}
+
- {/* Footer */}
- {/* TODO: add license */}
-
+ {/* Footer */}
+ {/* TODO: add license */}
+
+
+
)
}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/BiomarkerTrainedModelsTable.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/BiomarkerTrainedModelsTable.tsx
index 4d877e70..7c22fe09 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/BiomarkerTrainedModelsTable.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/BiomarkerTrainedModelsTable.tsx
@@ -218,10 +218,10 @@ export const BiomarkerTrainedModelsTable = (props: BiomarkerTrainedModelsPanelPr
headers={[
{ name: intl.formatMessage({ id: 'common.name' }), serverCodeToSort: 'name', width: 3 },
{ name: intl.formatMessage({ id: 'common.description' }), serverCodeToSort: 'description', width: 4 },
- { name: intl.formatMessage({ id: 'biomarkerTrainedModelsTable.header.state' }), serverCodeToSort: 'state', width: 1 },
+ { name: intl.formatMessage({ id: 'common.state' }), serverCodeToSort: 'state', width: 1 },
{ name: intl.formatMessage({ id: 'biomarkerTrainedModelsTable.header.model' }), serverCodeToSort: 'fitness_function', width: 1 },
- { name: intl.formatMessage({ id: 'biomarkerTrainedModelsTable.header.date' }), serverCodeToSort: 'created' },
- { name: intl.formatMessage({ id: 'biomarkerTrainedModelsTable.header.metric' }), serverCodeToSort: 'fitness_metric' },
+ { name: intl.formatMessage({ id: 'common.date' }), serverCodeToSort: 'created' },
+ { name: intl.formatMessage({ id: 'common.metric' }), serverCodeToSort: 'fitness_metric' },
{ name: intl.formatMessage({ id: 'biomarkerTrainedModelsTable.header.bestCVMetric' }), serverCodeToSort: 'best_fitness_value' },
{ name: intl.formatMessage({ id: 'biomarkerTrainedModelsTable.header.datasets' }) },
...actionColumn
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/ModelDetailsPanels.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/ModelDetailsPanels.tsx
index 7a3a4c08..7cd57673 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/ModelDetailsPanels.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/ModelDetailsPanels.tsx
@@ -51,7 +51,7 @@ const GeneralMetrics = (props: GeneralMetricsProps) => {
- {intl.formatMessage({ id: 'modelDetails.general.randomState' })} {props.data.random_state ?? '-'}
+ {intl.formatMessage({ id: 'common.randomState' })} {props.data.random_state ?? '-'}
@@ -77,7 +77,7 @@ const ClusteringModelDetailsPanel = (props: ClusteringModelDetailsPanelProps) =>
- {intl.formatMessage({ id: 'modelDetails.clustering.algorithm' })}
+ {intl.formatMessage({ id: 'common.algorithm' })}
@@ -87,7 +87,7 @@ const ClusteringModelDetailsPanel = (props: ClusteringModelDetailsPanelProps) =>
- {intl.formatMessage({ id: 'modelDetails.clustering.scoringMethod' })}
+ {intl.formatMessage({ id: 'common.scoringMethod' })}
@@ -96,7 +96,7 @@ const ClusteringModelDetailsPanel = (props: ClusteringModelDetailsPanelProps) =>
- {intl.formatMessage({ id: 'modelDetails.clustering.numberOfClusters' })} {props.data.n_clusters}
+ {intl.formatMessage({ id: 'common.nClusters' })} {props.data.n_clusters}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentsTable.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentsTable.tsx
index 9d581863..1693f136 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentsTable.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentsTable.tsx
@@ -171,9 +171,9 @@ export const InferenceExperimentsTable = (props: InferenceExperimentsTableProps)
headers={[
{ name: intl.formatMessage({ id: 'common.name' }), serverCodeToSort: 'name', width: 3 },
{ name: intl.formatMessage({ id: 'common.description' }), serverCodeToSort: 'description', width: 4 },
- { name: intl.formatMessage({ id: 'inference.table.columns.state' }), serverCodeToSort: 'state', textAlign: 'center' },
+ { name: intl.formatMessage({ id: 'common.state' }), serverCodeToSort: 'state', textAlign: 'center' },
{ name: intl.formatMessage({ id: 'inference.table.columns.model' }), serverCodeToSort: 'model', width: 1 },
- { name: intl.formatMessage({ id: 'inference.table.columns.date' }), serverCodeToSort: 'created' },
+ { name: intl.formatMessage({ id: 'common.date' }), serverCodeToSort: 'created' },
{ name: intl.formatMessage({ id: 'inference.table.columns.dataset' }) },
{ name: intl.formatMessage({ id: 'common.actions' }) }
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/NewInferenceExperimentModal.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/NewInferenceExperimentModal.tsx
index aea77731..b975eab1 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/NewInferenceExperimentModal.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/NewInferenceExperimentModal.tsx
@@ -314,7 +314,7 @@ export const NewInferenceExperimentModal = (props: NewInferenceExperimentModalPr
{/* Basic data */}
- {intl.formatMessage({ id: 'inference.new.basicData' })}
+ {intl.formatMessage({ id: 'common.basicData' })}
@@ -329,7 +329,7 @@ export const NewInferenceExperimentModal = (props: NewInferenceExperimentModalPr
@@ -397,7 +397,7 @@ export const NewInferenceExperimentModal = (props: NewInferenceExperimentModalPr
}}
disabled={!selectedTrainedModelIsValid}
>
- {intl.formatMessage({ id: 'inference.new.continue' })}
+ {intl.formatMessage({ id: 'common.continue' })}
)}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndGroupsInferenceTable.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndGroupsInferenceTable.tsx
index d915da4e..c774d6eb 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndGroupsInferenceTable.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndGroupsInferenceTable.tsx
@@ -50,7 +50,7 @@ export const SamplesAndGroupsInferenceTable = (props: SamplesAndGroupsInferenceT
headers={[
{ name: intl.formatMessage({ id: 'common.sample' }), serverCodeToSort: 'sample', width: 3, textAlign: 'center' },
- { name: intl.formatMessage({ id: 'inference.table.columns.cluster' }), serverCodeToSort: 'cluster', width: 2, textAlign: 'center' }
+ { name: intl.formatMessage({ id: 'common.cluster' }), serverCodeToSort: 'cluster', width: 2, textAlign: 'center' }
]}
queryParams={{
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/gene-ontology/GeneOntologyCytoscapeChart.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/gene-ontology/GeneOntologyCytoscapeChart.tsx
index 429c6a37..30c8764a 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/gene-ontology/GeneOntologyCytoscapeChart.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/gene-ontology/GeneOntologyCytoscapeChart.tsx
@@ -27,7 +27,7 @@ const CytoscapeLegends = () => {
return (
- {intl.formatMessage({ id: 'geneOntology.legend.relations' })}
+ {intl.formatMessage({ id: 'common.relations' })}
@@ -204,7 +204,7 @@ export const GeneOntologyCytoscapeChart = (props: GeneOntologyCytoscapeChartProp
{/* Form for termsRelatedToTermForm */}
- {intl.formatMessage({ id: 'geneOntology.form.relations' })}
+ {intl.formatMessage({ id: 'common.relations' })}
{Object.entries(OntologyRelationTermToTermFilter)
.filter(([_key, value]) => value !== OntologyRelationTermToTermFilter.IS_A)
.map(([key, value]) => (
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/GeneAssociationsNetworkPanel.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/GeneAssociationsNetworkPanel.tsx
index 6b08ec48..335d1a41 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/GeneAssociationsNetworkPanel.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/GeneAssociationsNetworkPanel.tsx
@@ -32,7 +32,7 @@ const CytoscapeLegends = () => {
return (
- {intl.formatMessage({ id: 'geneAssociations.legend.relations' })}
+ {intl.formatMessage({ id: 'common.relations' })}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/NewStatisticalValidationModal.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/NewStatisticalValidationModal.tsx
index 3f196522..d6acccef 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/NewStatisticalValidationModal.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/NewStatisticalValidationModal.tsx
@@ -320,7 +320,7 @@ export const NewStatisticalValidationModal = (props: NewStatisticalValidationMod
{/* Basic data */}
- {intl.formatMessage({ id: 'newStatValidation.header.basicData' })}
+ {intl.formatMessage({ id: 'common.basicData' })}
@@ -401,7 +401,7 @@ export const NewStatisticalValidationModal = (props: NewStatisticalValidationMod
}}
disabled={!selectedTrainedModelIsValid}
>
- {intl.formatMessage({ id: 'newStatValidation.button.continue' })}
+ {intl.formatMessage({ id: 'common.continue' })}
)}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/StatisticalValidationsTable.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/StatisticalValidationsTable.tsx
index 03b9f5b5..b1a03e1b 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/StatisticalValidationsTable.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/StatisticalValidationsTable.tsx
@@ -173,9 +173,9 @@ export const StatisticalValidationsTable = (props: StatisticalValidationsTablePr
headers={[
{ name: intl.formatMessage({ id: 'common.name' }), serverCodeToSort: 'name', width: 3 },
{ name: intl.formatMessage({ id: 'common.description' }), serverCodeToSort: 'description', width: 4 },
- { name: intl.formatMessage({ id: 'statValidationsTable.headers.state' }), serverCodeToSort: 'state', textAlign: 'center' },
+ { name: intl.formatMessage({ id: 'common.state' }), serverCodeToSort: 'state', textAlign: 'center' },
{ name: intl.formatMessage({ id: 'statValidationsTable.headers.model' }), textAlign: 'center', width: 2 },
- { name: intl.formatMessage({ id: 'statValidationsTable.headers.date' }), serverCodeToSort: 'created' },
+ { name: intl.formatMessage({ id: 'common.date' }), serverCodeToSort: 'created' },
{ name: intl.formatMessage({ id: 'statValidationsTable.headers.datasets' }) },
{ name: intl.formatMessage({ id: 'common.actions' }) }
]}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/SamplesAndGroupsTable.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/SamplesAndGroupsTable.tsx
index 8499bf5b..e73e8a50 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/SamplesAndGroupsTable.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/SamplesAndGroupsTable.tsx
@@ -25,12 +25,12 @@ export const SamplesAndGroupsTable = (props: SamplesAndGroupsTableProps) => {
headers={[
{ name: intl.formatMessage({ id: 'common.sample' }), serverCodeToSort: 'sample', width: 3 },
- { name: intl.formatMessage({ id: 'samplesAndGroupsTable.header.cluster' }), serverCodeToSort: 'cluster', width: 2 }
+ { name: intl.formatMessage({ id: 'common.cluster' }), serverCodeToSort: 'cluster', width: 2 }
]}
queryParams={{ statistical_validation_pk: props.selectedStatisticalValidation.id }}
customFilters={[
{
- label: intl.formatMessage({ id: 'samplesAndGroupsTable.filter.cluster' }),
+ label: intl.formatMessage({ id: 'common.cluster' }),
keyForServer: 'cluster',
defaultValue: '',
placeholder: intl.formatMessage({ id: 'samplesAndGroupsTable.filter.cluster.placeholder' }),
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/StatisticalValidationResultBestFeatures.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/StatisticalValidationResultBestFeatures.tsx
index bcb00df3..65bb77c8 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/StatisticalValidationResultBestFeatures.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/result/StatisticalValidationResultBestFeatures.tsx
@@ -78,7 +78,7 @@ export const StatisticalValidationResultBestFeatures = (props: StatisticalValida
const moleculesNames = statValidationData ? statValidationData.map((elem) => elem.identifier) : []
const chartSeries: ApexAxisChartSeries = [{
- name: intl.formatMessage({ id: 'statValidationBestFeatures.series.coefficient' }),
+ name: intl.formatMessage({ id: 'common.coefficient' }),
data: coefficients
}]
@@ -128,7 +128,7 @@ export const StatisticalValidationResultBestFeatures = (props: StatisticalValida
xaxis: {
categories: moleculesNames,
title: {
- text: intl.formatMessage({ id: 'statValidationBestFeatures.axis.coefficient' })
+ text: intl.formatMessage({ id: 'common.coefficient' })
},
type: 'category',
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/trained-models/NewClusteringModelForm.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/trained-models/NewClusteringModelForm.tsx
index da56d20f..e28fc969 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/trained-models/NewClusteringModelForm.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/trained-models/NewClusteringModelForm.tsx
@@ -23,7 +23,7 @@ export const NewClusteringModelForm = (props: NewClusteringModelFormProps) => {
fluid
selectOnBlur={false}
label={(
-
+
{
)}
options={clusteringAlgorithmOptions}
- placeholder={intl.formatMessage({ id: 'newClusteringForm.placeholder.algorithm' })}
+ placeholder={intl.formatMessage({ id: 'common.algorithm' })}
name='algorithm'
value={props.parameters.algorithm}
onChange={props.handleChangeParams}
@@ -50,7 +50,7 @@ export const NewClusteringModelForm = (props: NewClusteringModelFormProps) => {
+
{
fluid
selectOnBlur={false}
label={(
-
+
{
fluid
selectOnBlur={false}
label={(
-
+
{
+
{
/>
)}
- placeholder={intl.formatMessage({ id: 'newClusteringForm.placeholder.integer' })}
+ placeholder={intl.formatMessage({ id: 'common.integerPlaceholder' })}
type='number'
step={1}
min={0}
@@ -137,7 +137,7 @@ export const NewClusteringModelForm = (props: NewClusteringModelFormProps) => {
+
{
/>
)}
- placeholder={intl.formatMessage({ id: 'newClusteringForm.placeholder.integer' })}
+ placeholder={intl.formatMessage({ id: 'common.integerPlaceholder' })}
type='number'
step={0.1}
min={0}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/trained-models/NewRFModelForm.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/trained-models/NewRFModelForm.tsx
index 0aea8e0c..0b27fdc0 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/trained-models/NewRFModelForm.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/trained-models/NewRFModelForm.tsx
@@ -87,7 +87,7 @@ export const NewRFModelForm = (props: NewSVMModelFormProps) => {
+
{
+
{
+
{
- {intl.formatMessage({ id: 'newTrainedModelModal.header.basicData' })}
+ {intl.formatMessage({ id: 'common.basicData' })}
{
/>
handleInputChanges(name, value as string | undefined)}
@@ -598,7 +598,7 @@ export const NewTrainedModelModal = (props: NewTrainedModelModalProps) => {
}}
disabled={isLastStep ? !formIsValid() : !modelIsValid}
>
- {isLastStep ? intl.formatMessage({ id: 'common.confirm' }) : intl.formatMessage({ id: 'newTrainedModelModal.button.continue' })}
+ {isLastStep ? intl.formatMessage({ id: 'common.confirm' }) : intl.formatMessage({ id: 'common.continue' })}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/CrossValidationInput.tsx b/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/CrossValidationInput.tsx
index 125fe9f6..5f84535c 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/CrossValidationInput.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/CrossValidationInput.tsx
@@ -22,8 +22,8 @@ export const CrossValidationInput = (props: CrossValidationInputProps) => {
{
+ const intl = useIntl()
+
/**
* Generates default table's headers
* @returns Default object for table's headers
@@ -45,7 +48,7 @@ export const FeatureSelectionPanel = (props: FeatureSelectionPanelProps) => {
const getDefaultHeaders = (): RowHeader[] => [
{ name: 'Name', serverCodeToSort: 'name', width: 3 },
{ name: 'Description', serverCodeToSort: 'description', width: 4 },
- { name: 'Tag', serverCodeToSort: 'tag', width: 2 },
+ { name: intl.formatMessage({ id: 'featureSelectionPanel.tag' }), serverCodeToSort: 'tag', width: 2 },
{ name: 'Date', serverCodeToSort: 'upload_date' },
{ name: '# mRNAS', serverCodeToSort: 'number_of_mrnas', width: 1 },
{ name: '# miRNAS', serverCodeToSort: 'number_of_mirnas', width: 1 },
@@ -183,19 +186,23 @@ export const FeatureSelectionPanel = (props: FeatureSelectionPanelProps) => {
1} onClick={() => handleGoBackPanel(props.handleGoBackStep1, props.featureSelection.step > 1)}>
- Step 1: {props.featureSelection.biomarker?.id ? `Selected ${props.featureSelection.biomarker?.name}` : 'Select biomarker'}
+
+ {intl.formatMessage({ id: 'featureSelectionPanel.step1' })}: {props.featureSelection.biomarker?.id
+ ? intl.formatMessage({ id: 'featureSelectionPanel.selectedBiomarker' }, { biomarker: props.featureSelection.biomarker?.name })
+ : intl.formatMessage({ id: 'featureSelectionPanel.selectBiomarker' })}
+
2} disabled={props.featureSelection.step === 1} onClick={() => handleGoBackPanel(props.handleGoBackStep2, props.featureSelection.step > 2)}>
- Step 2: Datasets
+ {intl.formatMessage({ id: 'featureSelectionPanel.step2' })}
3} disabled={props.featureSelection.step < 3}>
- Step 3: Feature selection
+ {intl.formatMessage({ id: 'featureSelectionPanel.step3' })}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/FeatureSelectionForm.tsx b/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/FeatureSelectionForm.tsx
index eb22b0cb..3497a9f9 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/FeatureSelectionForm.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/FeatureSelectionForm.tsx
@@ -68,7 +68,7 @@ export const FeatureSelectionForm = (props: FeatureSelectionFormProps) => {
fluid
style={{ minWidth: '180px', maxWidth: '100% ' }}
type='number'
- label={intl.formatMessage({ id: 'featureSelection.numberOfClusters' })}
+ label={intl.formatMessage({ id: 'common.nClusters' })}
name='nClusters'
min={2}
max={10}
@@ -92,7 +92,7 @@ export const FeatureSelectionForm = (props: FeatureSelectionFormProps) => {
fluid
style={{ minWidth: '180px', maxWidth: '100% ' }}
type='number'
- label={intl.formatMessage({ id: 'featureSelection.penalizer' })}
+ label={intl.formatMessage({ id: 'common.penalizer' })}
name='penalizer'
min={0}
value={fitnessFunctionParameters.clusteringParameters.penalizer}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/FeatureSelectionStep3.tsx b/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/FeatureSelectionStep3.tsx
index f7ab0ce5..459aff6a 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/FeatureSelectionStep3.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/modalContentBiomarker/featureSelectionPanel/steps/FeatureSelectionStep3.tsx
@@ -137,10 +137,10 @@ export const FeatureSelectionStep3 = (props: FeatureSelectionStep3Props) => {
{
{
{
{
{
{
{
{
return (
<>
{
- {intl.formatMessage({ id: 'clustering.metric' })}
+ {intl.formatMessage({ id: 'common.metric' })}
{
- {intl.formatMessage({ id: 'clustering.scoringMethod' })}
+ {intl.formatMessage({ id: 'common.scoringMethod' })}
{
{
- return (
-
-
-
-
-
- Frequently Asked Questions
-
+ return (
+
+
+
+
+
+ Frequently Asked Questions
+
+
+ {/* Question 1: What is Multiomix? */}
+
+ Multiomix is a cloud-based, open-source platform for investigating genomic and epigenomic
+ events associated with the modulation of gene expression, with a focus on biomarker discovery
+ and multi-omic analysis in cancer. It integrates data retrieval, aggregation, analysis, and
+ visualization functions for both public and user-uploaded data. (Paper )
+
+ )}
+ />
+
+ {/* Question 2: What kind of analysis can I do? */}
+
+ Multiomix allows you to run correlation analyses between mRNA and other non-mRNA omic layers,
+ particularly miRNA, DNA methylation, and CNA. It also includes survival analysis, statistical
+ validations, model training, and inference on new datasets. In terms of biomarkers, the platform
+ enables identifying, managing, and evaluating signatures composed of different omic variables,
+ exploring their prognostic or predictive value, training models on those biomarkers, and
+ reusing them for validation and inference on new cohorts.
+
+ )}
+ />
+
+ {/* Question 3: Pipelines and statistical methods */}
+
+
+ The platform provides three core pipelines: miRNA-mRNA, DNA methylation-mRNA, and CNA-mRNA.
+ In these workflows, users select datasets, filters, correlation method, and p-value adjustment,
+ then explore results alongside clinical and follow-up information.
+
+
+ For correlation, Multiomix supports Pearson, Spearman, and Kendall. For multiple testing
+ correction, it supports Benjamini-Hochberg, Benjamini-Yekutieli, and Bonferroni, among others.
+ Survival analyses such as Kaplan-Meier and Log-rank are also included to estimate the biological
+ impact of detected events.
+
+
+ A dedicated panel for biomarker management, optimization, and evaluation supports biomarkers
+ composed of mRNA, miRNA, CNA, and methylation sites. It allows training clustering,
+ Survival SVM, and Random Survival Forest models to assess prognostic or predictive power,
+ and reusing already trained models for new validations and inferences without retraining from scratch.
+ For existing biomarkers, the platform also offers optimization through multiple feature selection methods.
+
+ >
+ )}
+ />
+
+ {/* Question 4: Uploading own data */}
+
+ Yes. Multiomix allows you to upload your own datasets in a validated manner, with format and
+ consistency checks. It also offers batch uploads for large datasets and an interactive table
+ with filters, search, pagination, sorting, and tagging to manage your data.
+
+ )}
+ />
+ {/* Question 5: Public datasets */}
+
+ Yes. The platform includes preloaded datasets retrieved programmatically from cBioPortal.
+ This allows you to work with both public and private data in the same environment.
+
+ )}
+ />
+
+ {/* Question 6: cBioPortal datasets preprocessing */}
+
+
+ Datasets from cBioPortal are synchronized regularly to ensure data consistency.
+ If there is an update that we miss, users can contact us directly.
+ Duplicate molecules are removed to keep the dataset clean.
+ Samples without information for a given molecule in a biomarker are excluded from trained models,
+ statistical validations, feature selection experiments, and inference steps.
+
+
+ Clinical data also undergo preprocessing: cases with NaN, empty or Null values are filtered out.
+ Additionally, cases with an event but survival time equal to zero are excluded (pending clarification from cBioPortal).
+
+ >
+ )}
+ />
+ {/* Question 7: Only for experts? */}
+
+ Not necessarily. Multiomix was designed to lower technical barriers and provide an accessible
+ experience for non-expert users as well, without sacrificing analytical rigor. Its goal is to
+ bring biomarker discovery closer to a broader range of research profiles through a friendly
+ interface, clear documentation, and usage guides, within an open and technology-democratization-oriented approach.
+
+ )}
+ />
+
+ {/* Question 8: Performance for correlation analysis */}
+
+ For large-scale correlation analysis, Multiomix developed its own tool called{' '}
+ GGCA , implemented
+ in Rust to improve performance and memory usage.
+
+ )}
+ />
- {/* Question 1: Datasets */}
-
-
- Datasets from cBioPortal are synchronized regularly to ensure data consistency.
- If there is an update that we miss, users can contact us directly.
- Duplicate molecules are removed to keep the dataset clean.
- Samples without information for a given molecule in a biomarker are excluded from trained models,
- statistical validations, feature selection experiments, and inference steps.
-
-
- Clinical data also undergo preprocessing: cases with NaN, empty or Null values are filtered out.
- Additionally, cases with an event but survival time equal to zero are excluded (pending clarification from cBioPortal).
-
- >
- }
- />
-
- {/* Question 2: Privacy */}
-
- Uploaded data is securely stored and only accessible to the uploading user.
- Once deleted, the data is permanently removed from our servers and cannot be recovered.
- No third parties have access to private user data.
-
- }
- />
+ {/* Question 9: Metaheuristics acceleration */}
+
+ Multiomix incorporates distributed computing optimizations over Apache Spark to accelerate
+ the evaluation of metaheuristic agents in feature selection processes. It also includes
+ internally developed distribution strategies designed to maximize the use of available
+ resources and achieve the best possible performance. (Source )
+
+ )}
+ />
+ {/* Question 10: Ecosystem integrations */}
+
+ Multiomix relies on BioAPI and Modulector for part of its functionality. Both platforms act
+ as abstraction layers for standardized access to biological data.{' '}
+ BioAPI exposes gene
+ nomenclature, expression, and pathway information through a REST API, while{' '}
+ Modulector centralizes
+ miRNA, gene, and methylation site data, and offers services related to PubMed evidence and news.
+
+ )}
+ />
+ {/* Question 11: Internal technologies */}
+
+ Multiomix is built as a Python/Rust web application. It uses Django on the backend, React
+ with TypeScript on the frontend, PostgreSQL for annotations, MongoDB for preloaded datasets,
+ and Redis/WebSocket for asynchronous execution and notifications. Celery is used for task
+ queues, with dependencies on Modulector and BioAPI. (
+ GitHub )
+
+ )}
+ />
-
+
+ {/* Question 12: Privacy */}
+
+ Uploaded data is securely stored and only accessible to the uploading user.
+ Once deleted, the data is permanently removed from our servers and cannot be recovered.
+ No third parties have access to private user data.
+
+ )}
+ />
+ {/* Question 13: Local installation */}
+
+ Yes. Multiomix can be deployed locally and its official repository includes installation
+ and development instructions, as well as support for quick deployments with Docker and
+ complementary installation of BioAPI and Modulector. The project is distributed under
+ the GPL-3.0 license, which promotes transparency, source code access, adaptability to
+ specific needs, and open community collaboration. (
+ GitHub )
+
+ )}
+ />
- {/* Question 3: Licenses */}
-
- For legal and transparency reasons, we provide a list of third-party libraries and tools used in this platform,
- along with their respective licenses. This ensures compliance and acknowledgment of the open-source
- community contributions that power our ecosystem.
-
-
- }
- />
+
+ {/* Question 14: Licenses */}
+
+ For legal and transparency reasons, we provide a list of third-party libraries and tools
+ used in this platform, along with their respective licenses. This ensures compliance and
+ acknowledgment of the open-source community contributions that power our ecosystem.
+
+ )}
+ />
+ {/* Question 15: Additional Links */}
+
+ Site Map
+ Contact Us
+ Terms and Conditions
+ Privacy Policy
+
+ )}
+ />
-
+
- {/* Question 4: Additional Links */}
-
- Site Map
- Contact Us
- Terms and Conditions
- Privacy Policy
-
- }
-
- />
-
-
-
-
-
- )
+
+
+
+
+
+ )
}
diff --git a/src/frontend/static/frontend/src/components/faq/FAQQuestionAndAnswer.tsx b/src/frontend/static/frontend/src/components/faq/FAQQuestionAndAnswer.tsx
index d7e6e6eb..6ab6f618 100644
--- a/src/frontend/static/frontend/src/components/faq/FAQQuestionAndAnswer.tsx
+++ b/src/frontend/static/frontend/src/components/faq/FAQQuestionAndAnswer.tsx
@@ -1,5 +1,5 @@
-import React from "react";
-import { Segment, Header } from "semantic-ui-react";
+import React from 'react'
+import { Segment, Header } from 'semantic-ui-react'
/**
* Props for the FAQQuestionAndAnswer component.
@@ -15,12 +15,11 @@ interface FAQQuestionAndAnswerProps {
/**
* Reusable component for displaying a FAQ question and its answer.
- *
* @param props - Object containing `segmentId`, `headerTitle`, and `answer`
* @returns A React component that displays a FAQ question and its answer.
-*/
+ */
export const FAQQuestionAndAnswer = (props: FAQQuestionAndAnswerProps) => {
- const { segmentId, headerTitle, answer } = props;
+ const { segmentId, headerTitle, answer } = props
return (
diff --git a/src/frontend/static/frontend/src/faq.tsx b/src/frontend/static/frontend/src/faq.tsx
index def10ef7..78f89215 100644
--- a/src/frontend/static/frontend/src/faq.tsx
+++ b/src/frontend/static/frontend/src/faq.tsx
@@ -4,4 +4,6 @@ import { FAQ } from './components/faq/FAQ'
const container = document.getElementById('faq-app')
const root = createRoot(container!)
+
+// eslint-disable-next-line @stylistic/jsx-pascal-case
root.render( )
diff --git a/src/frontend/static/frontend/src/locales/en.ts b/src/frontend/static/frontend/src/locales/en.ts
index ee6dc86a..d464617b 100644
--- a/src/frontend/static/frontend/src/locales/en.ts
+++ b/src/frontend/static/frontend/src/locales/en.ts
@@ -16,6 +16,27 @@ export default {
'common.description': 'Description',
'common.requiredField': 'Required field',
'common.model': 'Model:',
+ 'common.date': 'Date',
+ 'common.datasets': 'Datasets',
+ // common Labels
+ 'common.algorithm': 'Algorithm',
+ 'common.nClusters': 'Number of clusters',
+ 'common.metric': 'Metric',
+ 'common.scoringMethod': 'Scoring method',
+ 'common.randomState': 'Random state',
+ 'common.penalizer': 'Penalizer',
+ 'common.integerPlaceholder': 'An integer number',
+ 'common.numberOfIterations': 'Number of iterations',
+ 'common.coefficient': 'Coefficient',
+ // common Forms and steps
+ 'common.basicData': 'Basic data',
+ 'common.descriptionOptional': 'Description (optional)',
+ 'common.continue': 'Continue',
+ 'common.numberOfFolds': 'Number of folds',
+ // common Tables and states
+ 'common.state': 'State',
+ 'common.cluster': 'Cluster',
+ 'common.relations': 'Relations',
// Auth/user
'auth.login': 'Log in',
@@ -75,9 +96,7 @@ export default {
'inference.delete.button': '{common.delete}',
'inference.table.title': 'Inference experiments',
- 'inference.table.columns.state': 'State',
'inference.table.columns.model': 'Model',
- 'inference.table.columns.date': 'Date',
'inference.table.columns.dataset': 'Datasets',
'inference.search.placeholder': 'Search by name or description',
@@ -86,16 +105,11 @@ export default {
'inference.results.title': 'See results',
'inference.results.tooltip': 'View experiment results',
// 6.NewInferenceExperimentModal.tsx
- 'inference.new.description': 'Description (optional)',
'inference.newInference.title': 'Create new inference experiment',
- 'inference.new.basicData': 'Basic data',
'inference.new.step1': 'Step 1: Trained model',
'inference.new.step2': 'Step 2: molecules datasets',
- 'inference.new.continue': 'Continue',
// 7.SamplesAndGroupsInferenceTable.tsx
- 'inference.table.columns.cluster': 'Cluster',
'inference.table.download.tooltip': 'Download results in a CSV file',
- 'inference.table.filter.cluster.label': 'Cluster',
'inference.table.filter.cluster.placeholder': 'Filter by cluster',
'inference.table.addClusterLabels': 'Add Cluster labels',
// 8.SamplesAndTimeInferenceCharts.tsx
@@ -111,8 +125,6 @@ export default {
'inference.timeTable.menu.charts.info': 'Shows some charts with the samples and their predicted hazard/survival time grouped by some condition',
'inference.timeTable.addRangeLabels': 'Add Range labels',
// 10.molecules/GeneOntologyCytoscapeChart.tsx
- 'geneOntology.legend.relations': 'Relations',
- 'geneOntology.form.relations': 'Relations',
'geneOntology.form.ontologyType': 'Ontology type',
'geneOntology.form.generalDepth': 'General depth',
'geneOntology.form.hierarchicalDepth': 'Hierarchical depth to children',
@@ -145,7 +157,6 @@ export default {
// 12.GENES.ActionableCancerGenesPanel.tsx
'actionableCancerGenes.panel.title': 'Actionable Cancer Genes Panel',
// 13.GeneAssociationsNetworkPanel
- 'geneAssociations.legend.relations': 'Relations',
'geneAssociations.relation.fusion': 'Fusion',
'geneAssociations.relation.coOccurrence': 'Co-occurrence',
'geneAssociations.relation.experimental': 'Experimental',
@@ -202,13 +213,9 @@ export default {
'moleculesTable.header.type': 'Type',
'moleculesTable.header.actions': 'Actions',
// 21.SamplesAndGroupsTable.tsx
- 'samplesAndGroupsTable.header.cluster': 'Cluster',
- 'samplesAndGroupsTable.filter.cluster': 'Cluster',
'samplesAndGroupsTable.filter.cluster.placeholder': 'Filter by cluster',
// 22.StatisticalValidationResultBestFeatures.tsx
- 'statValidationBestFeatures.series.coefficient': 'Coefficient',
'statValidationBestFeatures.axis.molecule': 'Molecule',
- 'statValidationBestFeatures.axis.coefficient': 'Coefficient',
'statValidationBestFeatures.context.features': 'significant features found for this statistical validation',
// 23.StatisticalValidationResultKaplanMeier.tsx
'kaplanMeier.axis.time': 'Time',
@@ -229,11 +236,8 @@ export default {
'statValidationMetrics.metric.r2Score': 'R2 score',
// 25.NewStatisticalValidationModal.tsx
'newStatValidation.header.create': 'Create new statistical validation',
- 'newStatValidation.header.basicData': 'Basic data',
- 'newStatValidation.form.descriptionOptional': 'Description (optional)',
'newStatValidation.step.trainedModel': 'Step 1: Trained model',
'newStatValidation.step.validationDatasets': 'Step 2: Validation datasets',
- 'newStatValidation.button.continue': 'Continue',
// 26.StatisticalValidationMenu.tsx
'statValidationMenu.bestFeatures': 'Most significant features',
'statValidationMenu.bestFeatures.info': 'Most significant features for the survival analysis',
@@ -248,9 +252,7 @@ export default {
'statValidationsTable.deleteValidation.header': 'Delete statistical validation',
'statValidationsTable.deleteValidation.confirm': 'Are you sure you want to delete the statistical validation {name}?',
'statValidationsTable.headerTitle': 'Statistical validations',
- 'statValidationsTable.headers.state': 'State',
'statValidationsTable.headers.model': 'Model',
- 'statValidationsTable.headers.date': 'Date',
'statValidationsTable.headers.datasets': 'Datasets',
'statValidationsTable.headers.actions': 'Actions',
'statValidationsTable.newValidation': 'New statistical validation',
@@ -258,18 +260,11 @@ export default {
'statValidationsTable.actions.stopValidation': 'Stop statistical validation',
'statValidationsTable.actions.deleteValidation': 'Delete statistical validation',
// 28.NewClusteringModelForm.tsx
- 'newClusteringForm.label.algorithm': 'Algorithm',
'newClusteringForm.placeholder.algorithm': 'Select an algorithm',
'newClusteringForm.label.searchOptimalClusters': 'Search for the optimal number of clusters',
- 'newClusteringForm.label.nClusters': 'Number of clusters',
'newClusteringForm.info.nClusters': 'The number of clusters to group the data into. The optimal number can be found by looking for the elbow in the curve of the sum of squared distances between samples and their closest cluster center.',
- 'newClusteringForm.label.metric': 'Metric',
'newClusteringForm.placeholder.metric': 'Select a metric',
- 'newClusteringForm.label.scoringMethod': 'Scoring method',
'newClusteringForm.placeholder.scoringMethod': 'Select a method',
- 'newClusteringForm.label.randomState': 'Random state',
- 'newClusteringForm.label.penalizer': 'Penalizer',
- 'newClusteringForm.placeholder.integer': 'An integer number',
'newClusteringForm.info.algorithm': 'K-Means: Groups data by minimizing intra-cluster variance; effective for RNA and miRNA. Spectral Clustering: Uses graph-based similarity to identify complex patterns; ideal for methylation and CNA. BK-Means: A hierarchical variation of K-Means, suitable for layered clustering of clinical and multi-omics datasets. Ward’s Method: Minimizes variance in hierarchical clustering; well-suited for combining RNA and methylation data.',
'newClusteringForm.info.metric': 'Cox Regression: A proportional hazards model to identify associations between multi-omics features and clinical outcomes. Log-Rank Test: A non-parametric test to compare survival distributions; currently not available.',
'newClusteringForm.info.scoringMethod': 'C-Index: A measure of concordance between predicted and observed survival outcomes; higher values indicate better performance. Log Likelihood: The probability of observing the data given the model; lower values indicate better performance.',
@@ -280,7 +275,6 @@ export default {
'newRFForm.info.searchOptimalTrees': 'This option is useful when the number of samples in the clinical data is small or there are few observed events; setting this value increases the robustness of the model in such cases, avoiding problems with NaN values.',
'newRFForm.label.maxDepth': 'Max depth',
'newRFForm.info.maxDepth': 'The maximum depth of the tree',
- 'newRFForm.label.randomState': 'Random state',
'newRFForm.info.randomState': 'Seed used by the random number generator',
'newRFForm.label.nEstimators': 'Number of trees',
'newRFForm.info.nEstimators': 'The number of trees (estimators) used in the Random Forest model.',
@@ -291,23 +285,17 @@ export default {
'newSVMForm.placeholder.kernel': 'Select a kernel',
'newSVMForm.label.maxIterations': 'Max iterations',
'newSVMForm.info.maxIterations': 'The maximum number of iterations to be run',
- 'newSVMForm.label.randomState': 'Random state',
'newSVMForm.info.randomState': 'Seed used by the random number generator',
// 31.NewTrainedModelModal
'newTrainedModelModal.header.create': 'Create new trained model',
- 'newTrainedModelModal.header.basicData': 'Basic data',
- 'newTrainedModelModal.placeholder.descriptionOptional': 'Description (optional)',
'newTrainedModelModal.step1.trainingParameters': 'Step 1: Training parameters',
'newTrainedModelModal.step2.trainingDatasets': 'Step 2: Training datasets',
- 'newTrainedModelModal.button.continue': 'Continue',
-
'newTrainedModelModal.header.selectModel': 'Select a new model to train',
'newTrainedModelModal.placeholder.selectModel': 'Select a model',
'newTrainedModelModal.header.selectModelParameters': 'Select model parameters',
'newTrainedModelModal.header.selectCVParameters': 'Select Cross Validation parameters',
- 'newTrainedModelModal.label.numberOfFolds': 'Number of folds',
'newTrainedModelModal.info.numberOfFolds': 'Defines the number of data splits for cross-validation; ensures robust model evaluation and prevents overfitting.',
// 32.BiomarkerTrainedModelsTable
'biomarkerTrainedModelsTable.header.stopTraining': 'Stop training',
@@ -316,10 +304,7 @@ export default {
'biomarkerTrainedModelsTable.header.deleteBiomarker': 'Delete Biomarker',
'biomarkerTrainedModelsTable.confirm.deleteBiomarker': 'Are you sure you want to delete the Biomarker {modelName}?',
'biomarkerTrainedModelsTable.header.trainedModels': 'Trained models',
- 'biomarkerTrainedModelsTable.header.state': 'State',
'biomarkerTrainedModelsTable.header.model': 'Model',
- 'biomarkerTrainedModelsTable.header.date': 'Date',
- 'biomarkerTrainedModelsTable.header.metric': 'Metric',
'biomarkerTrainedModelsTable.header.bestCVMetric': 'Best CV metric',
'biomarkerTrainedModelsTable.header.datasets': 'Datasets',
'biomarkerTrainedModelsTable.header.actions': 'Actions',
@@ -331,10 +316,6 @@ export default {
'biomarkerTrainedModelsTable.button.deleteTrainedModelNotAllowed': 'Trained model cannot be deleted as it has related statistical validations and/or inference experiments',
// 33.ModelDetailsPanels
'modelDetails.general.bestFitnessValue': 'Best fitness value:',
- 'modelDetails.general.randomState': 'Random state:',
- 'modelDetails.clustering.algorithm': 'Algorithm:',
- 'modelDetails.clustering.scoringMethod': 'Scoring method:',
- 'modelDetails.clustering.numberOfClusters': 'Number of clusters:',
'modelDetails.svm.task': 'Task:',
'modelDetails.rf.numberOfEstimators': 'Number of estimators:',
'modelDetails.rf.maxDepth': 'Max. depth:',
@@ -379,59 +360,52 @@ export default {
'biomarkerType.featureSelection.description': 'As a starting point, you can select a previously discovered Biomarker, a well-known Biomarker, or a superset of genes that you would like to test. This method will select the molecular subset that fits the better prediction',
// 38.BBHAAdvanced
'bbha.numberOfStars': 'Number of stars',
- 'bbha.integerPlaceholder': 'An integer number',
'bbha.numberOfStars.info': 'Number of stars in the Binary Black Hole Algorithm. Each of these stars evaluates a different subset of features. Increasing this number increases the chances of evaluating the most optimal subset but delays more the result of the experiment',
- 'bbha.numberOfIterations': 'Number of iterations',
'bbha.numberOfIterations.info': 'Number of iterations in the Binary Black Hole Algorithm. In each of the iterations, the fitness function for each of the stars with its corresponding subset of features is computed. Increasing this number allows to evaluate more combinations of features but delays more the result of the experiment',
'bbha.version': 'BBHA Version',
'bbha.version.original': 'The Original approach executes the original Binary Black Hole Algorithm as defined in',
'bbha.version.v2': 'Version 2 is an improved version defined in this',
- 'bbha.coefficient': 'Coefficient',
'bbha.coefficientExplanation': 'Coefficient specified in the',
'bbha.useSpark': 'Try to optimize using Apache Spark',
'bbha.useSpark.info': 'If this option is enabled, the experiment will be executed (if possible) using Apache Spark to optimize execution times',
// 39.CoxRegressionAdvanced
'coxRegression.keepTopN': 'Keep top N',
- 'coxRegression.integerPlaceholder': 'An integer number',
'coxRegression.keepTopN.info': 'Maximum number of features to be retained after processing. The features are ordered in descending order by their coefficients, keeping the most significant ones first. If this value is left empty, all those whose coefficients are different from 0 will be retained',
// 40.GAAdvanced
'ga.populationSize': 'Population size',
- 'ga.integerPlaceholder': 'An integer number',
'ga.populationSize.info': 'Number of candidate solutions (individuals or potential solutions) that coexist in each generation of the genetic algorithm. Increasing this number allows to evaluate more combinations of features but delays more the result of the experiment',
'ga.mutationRate': 'Mutation rate',
'ga.floatPlaceholder': 'A float number',
'ga.mutationRate.info': 'Determines the probability that a bit (binary digit) in a candidate solution will be altered or flipped randomly during the evolution process. This option introduces small random changes to explore new possibilities.',
- 'ga.numberOfIterations': 'Number of iterations',
'ga.numberOfIterations.info': 'Number of iterations in the Genetic Algorithms. In each of the iterations, the fitness function for each candidate solution with its corresponding subset of features is computed. Increasing this number allows to evaluate more combinations of features but delays more the result of the experiment',
'ga.useSpark': 'Try to optimize using Apache Spark',
'ga.useSpark.info': 'If this option is enabled, the experiment will be executed (if possible) using',
// 41.ClusteringPanel
- 'clustering.algorithm': 'Algorithm',
'clustering.algorithm.placeholder': 'Clustering Algorithm',
- 'clustering.metric': 'Metric',
- 'clustering.scoringMethod': 'Scoring method',
// 42.RFPanel
'rf.numberOfEstimators': 'Number of estimators',
'rf.maxDepth': 'Maximum depth',
- 'rf.integerPlaceholder': 'An integer number',
// 43.SVMPanel
'svm.kernel.placeholder': 'Select a Kernel',
// 44.FeatureSelectionForm
'featureSelection.fitnessFunction': 'Fitness function',
'featureSelection.searchOptimalClusters': 'Search for the optimal number of clusters (soon)',
- 'featureSelection.numberOfClusters': 'Number of clusters',
- 'featureSelection.penalizer': 'Penalizer',
'featureSelection.maxIterations': 'Max iterations',
// 45.FeatureSelectionStep1
'featureSelectionStep1.headerTitle': 'Biomarkers',
'featureSelectionStep1.searchPlaceholder': 'Search by name',
// 46.FeatureSelectionStep3
- 'featureSelectionStep3.algorithm': 'Algorithm',
'featureSelectionStep3.blindSearch': 'Blind Search',
'featureSelectionStep3.expertMode': 'Expert mode',
'featureSelectionStep3.geneticAlgorithms': 'Genetic Algorithms',
// 47.CrossValidationInput
- 'crossValidation.numberOfFolds': 'Number of folds',
'crossValidation.integerPlaceholder': 'An integer number',
+ // 48.FeatureSelectionPanel
+ 'featureSelectionPanel.tag': 'Tag',
+ 'featureSelectionPanel.step1': 'Step 1',
+ 'featureSelectionPanel.step2': 'Step 2: Datasets',
+ 'featureSelectionPanel.step3': 'Step 3: Feature selection',
+ 'featureSelectionPanel.selectBiomarker': 'Select biomarker',
+ 'featureSelectionPanel.selectedBiomarker': 'Selected {biomarker}',
}
diff --git a/src/frontend/static/frontend/src/locales/es.ts b/src/frontend/static/frontend/src/locales/es.ts
index 8b0cb6ce..7221bbe3 100644
--- a/src/frontend/static/frontend/src/locales/es.ts
+++ b/src/frontend/static/frontend/src/locales/es.ts
@@ -16,6 +16,26 @@ export default {
'common.description': 'Descripción',
'common.requiredField': 'Campo obligatorio',
'common.model': 'Modelo:',
+ 'common.date': 'Fecha',
+ 'common.datasets': 'Conjuntos de datos',
+ // Common Labels
+ 'common.algorithm': 'Algoritmo',
+ 'common.nClusters': 'Número de clusters',
+ 'common.metric': 'Métrica',
+ 'common.scoringMethod': 'Método de puntuación',
+ 'common.randomState': 'Estado aleatorio',
+ 'common.penalizer': 'Penalizador',
+ 'common.integerPlaceholder': 'Un número entero',
+ 'common.numberOfIterations': 'Número de iteraciones',
+ 'common.coefficient': 'Coeficiente',
+ // Forms and steps
+ 'common.basicData': 'Datos básicos',
+ 'common.descriptionOptional': 'Descripción (opcional)',
+ 'common.continue': 'Continuar',
+ // common Tables and states
+ 'common.state': 'Estado',
+ 'common.cluster': 'Cluster',
+ 'common.relations': 'Relaciones',
// Auth/usuario
'auth.login': 'Iniciar sesión',
@@ -76,9 +96,7 @@ export default {
'inference.delete.button': '{common.delete}',
'inference.table.title': 'Experimentos de inferencia',
- 'inference.table.columns.state': 'Estado',
'inference.table.columns.model': 'Modelo',
- 'inference.table.columns.date': 'Fecha',
'inference.table.columns.dataset': 'Conjuntos de datos',
'inference.table.columns.actions': 'Acciones',
@@ -88,16 +106,11 @@ export default {
'inference.results.title': 'Ver resultados',
'inference.results.tooltip': 'Eliminar experimento',
// 6.NewInferenceExperimentModal.tsx
- 'inference.new.description': 'Descripción (opcional)',
'inference.newInference.title': 'Crear nuevo experimento de inferencia',
- 'inference.new.basicData': 'Datos básicos',
'inference.new.step1': 'Paso 1: Modelo entrenado',
'inference.new.step2': 'Paso 2: Conjuntos de datos de moléculas',
- 'inference.new.continue': 'Continuar',
// 7.SamplesAndGroupsInferenceTable.tsx
- 'inference.table.columns.cluster': 'Grupo',
'inference.table.download.tooltip': 'Descargar resultados en un archivo CSV',
- 'inference.table.filter.cluster.label': 'Grupo',
'inference.table.filter.cluster.placeholder': 'Filtrar por grupo',
'inference.table.addClusterLabels': 'Agregar etiquetas de grupo',
// 8.SamplesAndTimeInferenceCharts.tsx
@@ -113,8 +126,6 @@ export default {
'inference.timeTable.menu.charts.info': 'Muestra gráficos con las muestras y su tiempo de riesgo/supervivencia predicho agrupado por alguna condición',
'inference.timeTable.addRangeLabels': 'Agregar etiquetas de rango',
// 10.molecules/GeneOntologyCytoscapeChart.tsx
- 'geneOntology.legend.relations': 'Relaciones',
- 'geneOntology.form.relations': 'Relaciones',
'geneOntology.form.ontologyType': 'Tipo de ontología',
'geneOntology.form.generalDepth': 'Profundidad general',
'geneOntology.form.hierarchicalDepth': 'Profundidad jerárquica hacia hijos',
@@ -147,7 +158,6 @@ export default {
// 12GENES.ActionableCancerGenesPanel.tsx
'actionableGenes.panel.title': 'Panel de genes de cáncer accionables',
// 13.GeneAssociationsNetworkPanel
- 'geneAssociations.legend.relations': 'Relaciones',
'geneAssociations.relation.fusion': 'Fusión',
'geneAssociations.relation.coOccurrence': 'Co-ocurrencia',
'geneAssociations.relation.experimental': 'Experimental',
@@ -206,14 +216,10 @@ export default {
'moleculesTable.search.label': 'Muestra',
// 21.SamplesAndGroupsTable.tsx
'samplesAndGroupsTable.header.sample': 'Muestra',
- 'samplesAndGroupsTable.header.cluster': 'Cluster',
- 'samplesAndGroupsTable.filter.cluster': 'Cluster',
'samplesAndGroupsTable.filter.cluster.placeholder': 'Filtrar por cluster',
'samplesAndGroupsTable.search.label': 'Muestra',
// 22.StatisticalValidationResultBestFeatures.tsx
- 'statValidationBestFeatures.series.coefficient': 'Coeficiente',
'statValidationBestFeatures.axis.molecule': 'Molécula',
- 'statValidationBestFeatures.axis.coefficient': 'Coeficiente',
'statValidationBestFeatures.context.features': 'características significativas para esta validación estadística',
// 23.StatisticalValidationResultKaplanMeier.tsx
'kaplanMeier.axis.time': 'Tiempo',
@@ -235,11 +241,8 @@ export default {
'statValidationMetrics.header.model': 'Modelo',
// 25.NewStatisticalValidationModal.tsx
'newStatValidation.header.create': 'Crear nueva validación estadística',
- 'newStatValidation.header.basicData': 'Datos básicos',
- 'newStatValidation.form.descriptionOptional': 'Descripción (opcional)',
'newStatValidation.step.trainedModel': 'Paso 1: Modelo entrenado',
'newStatValidation.step.validationDatasets': 'Paso 2: Conjuntos de validación',
- 'newStatValidation.button.continue': 'Continuar',
// 26.StatisticalValidationMenu.tsx
'statValidationMenu.bestFeatures': 'Características más significativas',
'statValidationMenu.bestFeatures.info': 'Características más significativas para el análisis de supervivencia',
@@ -252,9 +255,7 @@ export default {
'statValidationsTable.deleteValidation.header': 'Eliminar validación estadística',
'statValidationsTable.deleteValidation.confirm': '¿Está seguro de que desea eliminar la validación estadística {name}?',
'statValidationsTable.headerTitle': 'Validaciones estadísticas',
- 'statValidationsTable.headers.state': 'Estado',
'statValidationsTable.headers.model': 'Modelo',
- 'statValidationsTable.headers.date': 'Fecha',
'statValidationsTable.headers.datasets': 'Conjuntos de datos',
'statValidationsTable.headers.actions': 'Acciones',
'statValidationsTable.newValidation': 'Nueva validación estadística',
@@ -262,18 +263,11 @@ export default {
'statValidationsTable.actions.stopValidation': 'Detener validación estadística',
'statValidationsTable.actions.deleteValidation': 'Eliminar validación estadística',
// 28.NewClusteringModelForm.tsx
- 'newClusteringForm.label.algorithm': 'Algoritmo',
'newClusteringForm.placeholder.algorithm': 'Seleccione un algoritmo',
'newClusteringForm.label.searchOptimalClusters': 'Buscar el número óptimo de clusters',
- 'newClusteringForm.label.nClusters': 'Número de clusters',
'newClusteringForm.info.nClusters': 'Número de clusters para agrupar los datos. El número óptimo puede encontrarse buscando el codo en la curva de la suma de distancias cuadradas entre muestras y su centro de cluster más cercano.',
- 'newClusteringForm.label.metric': 'Métrica',
'newClusteringForm.placeholder.metric': 'Seleccione una métrica',
- 'newClusteringForm.label.scoringMethod': 'Método de puntuación',
'newClusteringForm.placeholder.scoringMethod': 'Seleccione un método',
- 'newClusteringForm.label.randomState': 'Semilla aleatoria',
- 'newClusteringForm.label.penalizer': 'Penalizador',
- 'newClusteringForm.placeholder.integer': 'Un número entero',
'newClusteringForm.info.algorithm': 'K-Means: agrupa datos minimizando la varianza intra-cluster; útil para RNA y miRNA. Spectral Clustering: usa similitud basada en grafos para patrones complejos; ideal para metilación y CNA. BK-Means: variación jerárquica de K-Means, adecuada para datasets clínicos y multi-ómicos. Método de Ward: minimiza la varianza en clustering jerárquico; útil para combinar RNA y metilación.',
'newClusteringForm.info.metric': 'Cox Regression: modelo de riesgos proporcionales para asociaciones entre multi-ómicos y resultados clínicos. Log-Rank Test: prueba no paramétrica para comparar distribuciones de supervivencia; actualmente no disponible.',
'newClusteringForm.info.scoringMethod': 'C-Index: medida de concordancia entre resultados predichos y observados; valores altos indican mejor desempeño. Log Likelihood: probabilidad de observar los datos dado el modelo; valores bajos indican mejor desempeño.',
@@ -284,7 +278,6 @@ export default {
'newRFForm.info.searchOptimalTrees': 'Esta opción es útil cuando el número de muestras en los datos clínicos es pequeño o hay pocos eventos observados; establecer este valor aumenta la robustez del modelo en tales casos, evitando problemas con valores NaN.',
'newRFForm.label.maxDepth': 'Profundidad máxima',
'newRFForm.info.maxDepth': 'La profundidad máxima del árbol',
- 'newRFForm.label.randomState': 'Estado aleatorio',
'newRFForm.info.randomState': 'Semilla utilizada por el generador de números aleatorios',
'newRFForm.label.nEstimators': 'Número de árboles',
'newRFForm.info.nEstimators': 'El número de árboles (estimadores) utilizados en el modelo Random Forest.',
@@ -295,23 +288,17 @@ export default {
'newSVMForm.placeholder.kernel': 'Seleccionar un kernel',
'newSVMForm.label.maxIterations': 'Iteraciones máximas',
'newSVMForm.info.maxIterations': 'El número máximo de iteraciones a ejecutar',
- 'newSVMForm.label.randomState': 'Estado aleatorio',
'newSVMForm.info.randomState': 'Semilla utilizada por el generador de números aleatorios',
// 31.NewTrainedModelModal
'newTrainedModelModal.header.create': 'Crear nuevo modelo entrenado',
- 'newTrainedModelModal.header.basicData': 'Datos básicos',
- 'newTrainedModelModal.placeholder.descriptionOptional': 'Descripción (opcional)',
'newTrainedModelModal.step1.trainingParameters': 'Paso 1: Parámetros de entrenamiento',
'newTrainedModelModal.step2.trainingDatasets': 'Paso 2: Conjuntos de datos de entrenamiento',
- 'newTrainedModelModal.button.continue': 'Continuar',
-
'newTrainedModelModal.header.selectModel': 'Seleccionar un nuevo modelo para entrenar',
'newTrainedModelModal.placeholder.selectModel': 'Seleccionar un modelo',
'newTrainedModelModal.header.selectModelParameters': 'Seleccionar parámetros del modelo',
'newTrainedModelModal.header.selectCVParameters': 'Seleccionar parámetros de validación cruzada',
- 'newTrainedModelModal.label.numberOfFolds': 'Número de particiones',
'newTrainedModelModal.info.numberOfFolds': 'Define el número de divisiones de datos para la validación cruzada; asegura una evaluación robusta del modelo y previene el sobreajuste.',
// 32.BiomarkerTrainedModelsTable
'biomarkerTrainedModelsTable.header.stopTraining': 'Detener entrenamiento',
@@ -320,10 +307,7 @@ export default {
'biomarkerTrainedModelsTable.header.deleteBiomarker': 'Eliminar biomarcador',
'biomarkerTrainedModelsTable.confirm.deleteBiomarker': '¿Está seguro de que desea eliminar el biomarcador {modelName}?',
'biomarkerTrainedModelsTable.header.trainedModels': 'Modelos entrenados',
- 'biomarkerTrainedModelsTable.header.state': 'Estado',
'biomarkerTrainedModelsTable.header.model': 'Modelo',
- 'biomarkerTrainedModelsTable.header.date': 'Fecha',
- 'biomarkerTrainedModelsTable.header.metric': 'Métrica',
'biomarkerTrainedModelsTable.header.bestCVMetric': 'Mejor métrica de validación cruzada',
'biomarkerTrainedModelsTable.header.datasets': 'Conjuntos de datos',
'biomarkerTrainedModelsTable.header.actions': 'Acciones',
@@ -335,10 +319,6 @@ export default {
'biomarkerTrainedModelsTable.button.deleteTrainedModelNotAllowed': 'El modelo entrenado no puede eliminarse porque tiene validaciones estadísticas y/o experimentos de inferencia relacionados',
// 33.ModelDetailsPanels
'modelDetails.general.bestFitnessValue': 'Mejor valor de fitness:',
- 'modelDetails.general.randomState': 'Estado aleatorio:',
- 'modelDetails.clustering.algorithm': 'Algoritmo:',
- 'modelDetails.clustering.scoringMethod': 'Método de puntuación:',
- 'modelDetails.clustering.numberOfClusters': 'Número de clusters:',
'modelDetails.svm.task': 'Tarea:',
'modelDetails.rf.numberOfEstimators': 'Número de estimadores:',
'modelDetails.rf.maxDepth': 'Profundidad máxima:',
@@ -383,59 +363,52 @@ export default {
'biomarkerType.featureSelection.description': 'Como punto de partida, puedes seleccionar un Biomarker previamente descubierto, un Biomarker reconocido, o un conjunto de genes que quieras probar. Este método seleccionará el subconjunto molecular que mejor se ajuste a la predicción',
// 38.BBHAAdvanced
'bbha.numberOfStars': 'Número de estrellas',
- 'bbha.integerPlaceholder': 'Un número entero',
'bbha.numberOfStars.info': 'Número de estrellas en el Binary Black Hole Algorithm. Cada una de estas estrellas evalúa un subconjunto diferente de features. Aumentar este número incrementa las chances de evaluar el subconjunto más óptimo pero retrasa más el resultado del experimento',
- 'bbha.numberOfIterations': 'Número de iteraciones',
'bbha.numberOfIterations.info': 'Número de iteraciones en el Binary Black Hole Algorithm. En cada iteración se calcula la función de fitness para cada estrella con su correspondiente subconjunto de features. Aumentar este número permite evaluar más combinaciones de features pero retrasa más el resultado del experimento',
'bbha.version': 'Versión de BBHA',
'bbha.version.original': 'El enfoque Original ejecuta el Binary Black Hole Algorithm tal como se definió en',
'bbha.version.v2': 'La Versión 2 es una versión mejorada definida en este',
- 'bbha.coefficient': 'Coeficiente',
'bbha.coefficientExplanation': 'Coeficiente especificado en el',
'bbha.useSpark': 'Intentar optimizar usando Apache Spark',
'bbha.useSpark.info': 'Si esta opción está habilitada, el experimento se ejecutará (si es posible) usando Apache Spark para optimizar los tiempos de ejecución',
// 39.CoxRegressionAdvanced
'coxRegression.keepTopN': 'Mantener los N principales',
- 'coxRegression.integerPlaceholder': 'Un número entero',
'coxRegression.keepTopN.info': 'Número máximo de features que se conservarán después del procesamiento. Las features se ordenan en orden descendente según sus coeficientes, manteniendo primero las más significativas. Si este valor se deja vacío, se conservarán todas aquellas cuyos coeficientes sean distintos de 0',
// 40.GAAdvanced
'ga.populationSize': 'Tamaño de la población',
- 'ga.integerPlaceholder': 'Un número entero',
'ga.populationSize.info': 'Número de soluciones candidatas (individuos o posibles soluciones) que coexisten en cada generación del Genetic Algorithm. Aumentar este número permite evaluar más combinaciones de features pero retrasa más el resultado del experimento',
'ga.mutationRate': 'Tasa de mutación',
'ga.floatPlaceholder': 'Un número decimal',
'ga.mutationRate.info': 'Determina la probabilidad de que un bit (dígito binario) en una solución candidata sea alterado o cambiado aleatoriamente durante el proceso de evolución. Esta opción introduce pequeños cambios aleatorios para explorar nuevas posibilidades.',
- 'ga.numberOfIterations': 'Número de iteraciones',
'ga.numberOfIterations.info': 'Número de iteraciones en el Genetic Algorithm. En cada iteración se calcula la función de fitness para cada solución candidata con su correspondiente subconjunto de features. Aumentar este número permite evaluar más combinaciones de features pero retrasa más el resultado del experimento',
'ga.useSpark': 'Intentar optimizar usando Apache Spark',
'ga.useSpark.info': 'Si esta opción está habilitada, el experimento se ejecutará (si es posible) usando',
// 41.ClusteringPanel
- 'clustering.algorithm': 'Algoritmo',
'clustering.algorithm.placeholder': 'Algoritmo de Clustering',
- 'clustering.metric': 'Métrica',
- 'clustering.scoringMethod': 'Método de puntuación',
// 42.RFPanel
'rf.numberOfEstimators': 'Número de estimadores',
'rf.maxDepth': 'Profundidad máxima',
- 'rf.integerPlaceholder': 'Un número entero',
// 43.SVMPanel
'svm.kernel.placeholder': 'Seleccionar un Kernel',
// 44.FeatureSelectionForm
'featureSelection.fitnessFunction': 'Función de fitness',
'featureSelection.searchOptimalClusters': 'Buscar el número óptimo de clusters (próximamente)',
- 'featureSelection.numberOfClusters': 'Número de clusters',
- 'featureSelection.penalizer': 'Penalizador',
'featureSelection.maxIterations': 'Máximo de iteraciones',
// 45.FeatureSelectionStep1
'featureSelectionStep1.headerTitle': 'Biomarcadores',
'featureSelectionStep1.searchPlaceholder': 'Buscar por nombre',
// 46.FeatureSelectionStep3
- 'featureSelectionStep3.algorithm': 'Algoritmo',
'featureSelectionStep3.blindSearch': 'Búsqueda exhaustiva',
'featureSelectionStep3.expertMode': 'Modo experto',
'featureSelectionStep3.geneticAlgorithms': 'Algoritmos genéticos',
// 47.CrossValidationInput
- 'crossValidation.numberOfFolds': 'Número de particiones',
'crossValidation.integerPlaceholder': 'Un número entero',
+ // 48.FeatureSelectionPanel
+ 'featureSelectionPanel.tag': 'Etiqueta',
+ 'featureSelectionPanel.step1': 'Paso 1',
+ 'featureSelectionPanel.step2': 'Paso 2: Conjuntos de datos',
+ 'featureSelectionPanel.step3': 'Paso 3: Selección de características',
+ 'featureSelectionPanel.selectBiomarker': 'Seleccionar biomarcador',
+ 'featureSelectionPanel.selectedBiomarker': 'Seleccionado {biomarker}',
}
From c5c851a533f17893686b7190488bbb30b05a2596 Mon Sep 17 00:00:00 2001
From: natharisa
Date: Thu, 28 May 2026 23:51:55 -0300
Subject: [PATCH 11/11] Translate advances
---
.../components/biomarkers/BiomarkersPanel.tsx | 98 ++-
.../cgds-panel/NewCGDSDatasetForm.tsx | 16 +-
.../cgds-panel/NewCGDSStudyForm.tsx | 28 +-
.../src/components/common/EditIcon.tsx | 4 +-
.../src/components/common/PaginatedTable.tsx | 15 +-
.../src/components/common/SourceSelectors.tsx | 32 +-
.../components/common/SwitchPublicButton.tsx | 14 +-
.../components/common/TableCellSources.tsx | 12 +-
.../src/components/common/TagForm.tsx | 6 +-
.../src/components/common/TagLabel.tsx | 27 +-
.../src/components/common/TryAgainSegment.tsx | 31 +-
.../common/boxplots/BoxplotsCommons.tsx | 20 +-
.../cluster-labels/ClusterLabelsSetModal.tsx | 21 +-
.../cluster-labels/ClusterLabelsSetSelect.tsx | 6 +-
.../NewClusterLabelsSetModal.tsx | 34 +-
.../NewPredictionRangeLabelsSetModal.tsx | 44 +-
.../PredictionRangeLabelsSetModal.tsx | 20 +-
.../PredictionRangeLabelsSetSelect.tsx | 178 ++--
.../DifferentialExpressionForm.tsx | 44 +-
...entialExpressionInputClinicalAttribute.tsx | 7 +-
.../DifferentialExpressionModalResults.tsx | 8 +-
...rentialExpressionModalResultsTableView.tsx | 34 +-
...ntialExpressionModalResultsVolcanoPlot.tsx | 16 +-
.../DifferentialExpressionPanel.tsx | 70 +-
.../differential-expression/VolcanoPlot.tsx | 2 +
.../frontend/src/components/faq/FAQ.tsx | 216 +++++
.../components/files-manager/FilesManager.tsx | 2 +
.../static/frontend/src/locales/en.ts | 734 ++++++++++++++++
.../static/frontend/src/locales/es.ts | 789 ++++++++++++++++++
29 files changed, 2185 insertions(+), 343 deletions(-)
create mode 100644 src/frontend/static/frontend/src/components/faq/FAQ.tsx
create mode 100644 src/frontend/static/frontend/src/locales/en.ts
create mode 100644 src/frontend/static/frontend/src/locales/es.ts
diff --git a/src/frontend/static/frontend/src/components/biomarkers/BiomarkersPanel.tsx b/src/frontend/static/frontend/src/components/biomarkers/BiomarkersPanel.tsx
index 177baab3..2a8270b8 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/BiomarkersPanel.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/BiomarkersPanel.tsx
@@ -26,6 +26,7 @@ import { SharedInstitutionsBiomarker, SharedInstitutionsBiomarkerPropsExtend } f
import { EditBiomarkerIcon } from './EditBiomarkerIcon'
import { SwitchPublicButton } from '../common/SwitchPublicButton'
import { PopupIcons } from '../common/PopupIcons'
+import { useIntl, IntlShape } from 'react-intl'
// URLs defined in biomarkers.html
declare const urlBiomarkersCRUD: string
@@ -101,10 +102,14 @@ interface BiomarkersPanelState {
modalUsers: SharedUsersBiomarkerPropsExtend,
}
+interface BiomarkersPanelProps {
+ intl: IntlShape
+}
+
/**
* Renders a CRUD panel for a Biomarker.
*/
-export class BiomarkersPanel extends React.Component {
+export class BiomarkersPanel extends React.Component {
abortController = new AbortController()
constructor (props) {
super(props)
@@ -334,6 +339,7 @@ export class BiomarkersPanel extends React.Component
-
+
- Are you sure you want to stop the experiment {biomarkerToStop.name} ?
+ {intl.formatMessage({ id: 'biomarkersPanel.stopExperiment.content' }, { name: biomarkerToStop.name })}
- Cancel
+ {intl.formatMessage({ id: 'common.cancel' })}
- Stop
+ {intl.formatMessage({ id: 'common.stop' })}
@@ -1169,6 +1175,7 @@ export class BiomarkersPanel extends React.Component {
+ const { intl } = this.props
const formBiomarker = this.state.formBiomarker
this.setState(prevState => ({
formBiomarker: {
@@ -1207,7 +1214,7 @@ export class BiomarkersPanel extends React.Component {
response.json().then((_jsonResponse) => {
- this.closeModalWithSuccessMsg('Biomarker created successfully')
+ this.closeModalWithSuccessMsg(intl.formatMessage({ id: 'biomarkersPanel.alert.successCreating' }))
}).catch((err) => {
console.error('Error parsing JSON ->', err)
})
@@ -1218,7 +1225,7 @@ export class BiomarkersPanel extends React.Component {
@@ -1236,7 +1243,7 @@ export class BiomarkersPanel extends React.Component {
response.json().then((_jsonResponse) => {
- this.closeModalWithSuccessMsg('Biomarker edited successfully')
+ this.closeModalWithSuccessMsg(intl.formatMessage({ id: 'biomarkersPanel.alert.successEditing' }))
}).catch((err) => {
console.error('Error parsing JSON ->', err)
})
@@ -1247,7 +1254,7 @@ export class BiomarkersPanel extends React.Component {
@@ -1515,22 +1522,24 @@ export class BiomarkersPanel extends React.Component
-
+
- Are you sure you want to delete the Biomarker {this.state.selectedBiomarkerToDeleteOrSync.name} ?
+ {intl.formatMessage({ id: 'biomarkersPanel.deleteModal.content' }, { name: this.state.selectedBiomarkerToDeleteOrSync.name })}
- Cancel
+ {intl.formatMessage({ id: 'common.cancel' })}
- Delete
+ {intl.formatMessage({ id: 'common.delete' })}
@@ -1668,6 +1677,7 @@ export class BiomarkersPanel extends React.Component {
+ const { intl } = this.props
// For short...
const fsSettings = this.state.featureSelection
@@ -1701,7 +1711,7 @@ export class BiomarkersPanel extends React.Component {
response.json().then((responseJSON) => {
if (responseJSON.ok) {
- this.closeModalWithSuccessMsg('Experiment submitted!')
+ this.closeModalWithSuccessMsg((intl.formatMessage({ id: 'biomarkersPanel.alert.successSubmitting' })))
this.setState({ featureSelection: this.getDefaultFeatureSelectionProps(), openCreateEditBiomarkerModal: false })
} else {
alertGeneralError()
@@ -1724,16 +1734,17 @@ export class BiomarkersPanel extends React.Component {
const id = tag.id as number
return { key: id, value: id, text: tag.name }
})
- tagOptions.unshift({ key: 'no_tag', text: 'No tag' })
+ tagOptions.unshift({ key: 'no_tag', text: intl.formatMessage({ id: 'biomarkersPanel.tags.noTag' }) })
// TODO: refactor Tag key as it's the same as AllExperimentsView.tsx and UserFilesView.tsx
return [
- { label: 'Tag', keyForServer: 'tag', defaultValue: '', placeholder: 'Select an existing Tag', options: tagOptions, width: 3 }
+ { label: intl.formatMessage({ id: 'biomarkersPanel.tags.label' }), keyForServer: 'tag', defaultValue: '', placeholder: intl.formatMessage({ id: 'biomarkersPanel.tags.placeholder' }), options: tagOptions, width: 3 }
]
}
@@ -1768,6 +1779,7 @@ export class BiomarkersPanel extends React.Component
- headerTitle='Biomarkers'
+ headerTitle={intl.formatMessage({ id: 'biomarkersPanel.table.headerTitle' })}
headers={[
- { name: 'Name', serverCodeToSort: 'name', width: 3 },
- { name: 'Description', serverCodeToSort: 'description', width: 4 },
- { name: 'Tag', serverCodeToSort: 'tag' },
- { name: 'State', serverCodeToSort: 'state', textAlign: 'center' },
- { name: 'Origin', serverCodeToSort: 'origin', textAlign: 'center' },
- { name: 'Date', serverCodeToSort: 'upload_date' },
+ { name: intl.formatMessage({ id: 'common.name' }), serverCodeToSort: 'name', width: 3 },
+ { name: intl.formatMessage({ id: 'common.description' }), serverCodeToSort: 'description', width: 4 },
+ { name: intl.formatMessage({ id: 'biomarkersPanel.table.column.tag' }), serverCodeToSort: 'tag' },
+ { name: intl.formatMessage({ id: 'common.state' }), serverCodeToSort: 'state', textAlign: 'center' },
+ { name: intl.formatMessage({ id: 'biomarkersPanel.table.column.origin' }), serverCodeToSort: 'origin', textAlign: 'center' },
+ { name: intl.formatMessage({ id: 'common.date' }), serverCodeToSort: 'upload_date' },
{ name: '# mRNAS', serverCodeToSort: 'number_of_mrnas', width: 1 },
{ name: '# miRNAS', serverCodeToSort: 'number_of_mirnas', width: 1 },
{ name: '# CNA', serverCodeToSort: 'number_of_cnas', width: 1 },
{ name: '# Methylation', serverCodeToSort: 'number_of_methylations', width: 1 },
- { name: 'Public', width: 1 },
- { name: 'Shared', width: 1 },
- { name: 'Actions', width: 2 }
+ { name: intl.formatMessage({ id: 'biomarkersPanel.table.column.public' }), width: 1 },
+ { name: intl.formatMessage({ id: 'biomarkersPanel.table.column.shared' }), width: 1 },
+ { name: intl.formatMessage({ id: 'common.actions' }), width: 2 }
]}
defaultSortProp={{ sortField: 'upload_date', sortOrderAscendant: false }}
customFilters={this.getDefaultFilters()}
showSearchInput
customElements={[
-
+
]}
- searchLabel='Name'
- searchPlaceholder='Search by name'
+ searchLabel={intl.formatMessage({ id: 'common.name' })}
+ searchPlaceholder={intl.formatMessage({ id: 'biomarkersPanel.table.searchPlaceholder' })}
urlToRetrieveData={urlBiomarkersCRUD}
updateWSKey='update_biomarkers'
mapFunction={(biomarker: BiomarkerSimple) => {
@@ -1841,14 +1853,14 @@ export class BiomarkersPanel extends React.Component
)
: (
@@ -1863,7 +1875,7 @@ export class BiomarkersPanel extends React.Component this.setState({ modalInstitutions: { ...this.state.modalInstitutions, biomarkerId: biomarker.id || 0, isOpen: true, user: biomarker.user } })}
>
@@ -1875,7 +1887,7 @@ export class BiomarkersPanel extends React.Component this.setState({ modalUsers: { ...this.state.modalUsers, biomarkerId: biomarker.id || 0, isOpen: true, user: biomarker.user } })}
>
@@ -1913,14 +1925,14 @@ export class BiomarkersPanel extends React.Component this.setState({ biomarkerToClone: biomarker })}
/>
{/* Stop button */}
{isInProcess && (
this.setState({ biomarkerToStop: biomarker })}
/>
)}
@@ -1928,7 +1940,7 @@ export class BiomarkersPanel extends React.Component this.confirmBiomarkerDeletion(biomarker)}
ownerId={biomarker.user.id}
@@ -1961,16 +1973,16 @@ export class BiomarkersPanel extends React.Component
-
+
- Are you sure you want to clone the Biomarker "{this.state.biomarkerToClone?.name} "?
+ {intl.formatMessage({ id: 'biomarkersPanel.cloneModal.content' }, { name: this.state.biomarkerToClone?.name })}
- Cancel
+ {intl.formatMessage({ id: 'common.cancel' })}
- Clone
+ {intl.formatMessage({ id: 'biomarkersPanel.cloneModal.button' })}
@@ -1988,8 +2000,8 @@ export class BiomarkersPanel extends React.Component this.handleChangeConfirmModalState(true, 'You are going to lose all the data inserted', 'Are you sure?', this.closeBiomarkerModal)}
+ cancelForm={() => this.handleChangeConfirmModalState(true, intl.formatMessage({ id: 'biomarkersPanel.confirmModal.loseData.header' }), intl.formatMessage({ id: 'biomarkersPanel.confirmModal.loseData.content' }), this.closeBiomarkerModal)}
/>
)}
diff --git a/src/frontend/static/frontend/src/components/cgds-panel/NewCGDSDatasetForm.tsx b/src/frontend/static/frontend/src/components/cgds-panel/NewCGDSDatasetForm.tsx
index ca3f39cb..0f9f0357 100644
--- a/src/frontend/static/frontend/src/components/cgds-panel/NewCGDSDatasetForm.tsx
+++ b/src/frontend/static/frontend/src/components/cgds-panel/NewCGDSDatasetForm.tsx
@@ -4,6 +4,7 @@ import { DjangoCGDSDataset, DjangoCGDSStudy } from '../../utils/django_interface
import { NameOfCGDSDataset, CGDSDatasetSeparator, Nullable } from '../../utils/interfaces'
import { checkedValidityCallback } from '../../utils/util_functions'
import { SurvivalTuplesForm } from '../survival/SurvivalTuplesForm'
+import { useIntl } from 'react-intl'
/** For reusability */
type HandleSurvivalChangesCallback = (datasetName: NameOfCGDSDataset, idx: number, name: string, value: any) => void
@@ -36,6 +37,7 @@ interface NewCGDSDatasetFormProps {
* @returns Component
*/
export const NewCGDSDatasetForm = (props: NewCGDSDatasetFormProps) => {
+ const intl = useIntl()
const checkedHandleFormChanges = checkedValidityCallback(
(name, value) => props.handleFormDatasetChanges(props.datasetName, name, value)
)
@@ -53,7 +55,7 @@ export const NewCGDSDatasetForm = (props: NewCGDSDatasetFormProps) => {
onChange={checkedHandleFormChanges}
loading={props.addingOrEditingCGDSStudy}
disabled={props.addingOrEditingCGDSStudy}
- placeholder='File Path'
+ placeholder={intl.formatMessage({ id: 'cgdsDatasetForm.filePath.placeholder' })}
maxLength={150}
/>
@@ -73,7 +75,7 @@ export const NewCGDSDatasetForm = (props: NewCGDSDatasetFormProps) => {
{ key: 'colon', text: 'Colon', value: CGDSDatasetSeparator.COLON },
{ key: 'white_space', text: 'White space', value: CGDSDatasetSeparator.WHITE_SPACE }
]}
- placeholder='Select separator'
+ placeholder={intl.formatMessage({ id: 'cgdsDatasetForm.separator.placeholder' })}
onChange={(_, { name, value }) => props.handleFormDatasetChanges(props.datasetName, name, value)}
/>
@@ -86,7 +88,7 @@ export const NewCGDSDatasetForm = (props: NewCGDSDatasetFormProps) => {
onChange={checkedHandleFormChanges}
loading={props.addingOrEditingCGDSStudy}
disabled={props.addingOrEditingCGDSStudy}
- placeholder='Observation'
+ placeholder={intl.formatMessage({ id: 'cgdsDatasetForm.observation.placeholder' })}
maxLength={300}
/>
@@ -100,7 +102,7 @@ export const NewCGDSDatasetForm = (props: NewCGDSDatasetFormProps) => {
onChange={checkedHandleFormChanges}
loading={props.addingOrEditingCGDSStudy}
disabled={props.addingOrEditingCGDSStudy}
- placeholder='Header Row Index (0 indexed)'
+ placeholder={intl.formatMessage({ id: 'cgdsDatasetForm.headerRowIndex.placeholder' })}
min={0}
/>
@@ -117,7 +119,7 @@ export const NewCGDSDatasetForm = (props: NewCGDSDatasetFormProps) => {
onChange={checkedHandleFormChanges}
loading={props.addingOrEditingCGDSStudy}
disabled={props.addingOrEditingCGDSStudy}
- placeholder="Mongo Collection's name"
+ placeholder={intl.formatMessage({ id: 'cgdsDatasetForm.mongoName.placeholder' })}
pattern='^[a-zA-Z]([a-zA-Z0-9]|_)*' // Starts with a letter, the letters, numbers or '_' only
maxLength={100}
/>
@@ -151,7 +153,7 @@ export const NewCGDSDatasetForm = (props: NewCGDSDatasetFormProps) => {
name='add'
color='green'
className='clickable pull-right'
- title='Add dataset'
+ title={intl.formatMessage({ id: 'cgdsDatasetForm.icon.add' })}
disabled={props.addingOrEditingCGDSStudy}
onClick={() => props.addCGDSDataset(props.datasetName)}
/>
@@ -161,7 +163,7 @@ export const NewCGDSDatasetForm = (props: NewCGDSDatasetFormProps) => {
name='trash'
color='red'
className='clickable pull-right'
- title='Remove dataset'
+ title={intl.formatMessage({ id: 'cgdsDatasetForm.icon.remove' })}
disabled={props.addingOrEditingCGDSStudy}
onClick={() => props.removeCGDSDataset(props.datasetName)}
/>
diff --git a/src/frontend/static/frontend/src/components/cgds-panel/NewCGDSStudyForm.tsx b/src/frontend/static/frontend/src/components/cgds-panel/NewCGDSStudyForm.tsx
index 693360b8..bac233a3 100644
--- a/src/frontend/static/frontend/src/components/cgds-panel/NewCGDSStudyForm.tsx
+++ b/src/frontend/static/frontend/src/components/cgds-panel/NewCGDSStudyForm.tsx
@@ -4,6 +4,7 @@ import { DjangoCGDSStudy } from '../../utils/django_interfaces'
import { NameOfCGDSDataset } from '../../utils/interfaces'
import { NewCGDSDatasetForm } from './NewCGDSDatasetForm'
import { parseValue, checkedValidityCallback } from '../../utils/util_functions'
+import { useIntl } from 'react-intl'
/**
* Component's props
@@ -30,6 +31,7 @@ interface NewCGDSStudyFormProps {
* @returns Component
*/
export const NewCGDSStudyForm = (props: NewCGDSStudyFormProps) => {
+ const intl = useIntl()
const checkedHandleFormChanges = checkedValidityCallback(props.handleFormChanges)
const isDisabled = props.newCGDSStudy.name.trim().length === 0 &&
props.newCGDSStudy.description.trim().length === 0 &&
@@ -45,7 +47,7 @@ export const NewCGDSStudyForm = (props: NewCGDSStudyFormProps) => {
- Add specification of CGDS Study
+ {intl.formatMessage({ id: 'cgdsStudyForm.header' })}
{/* Name */}
@@ -58,7 +60,7 @@ export const NewCGDSStudyForm = (props: NewCGDSStudyFormProps) => {
onChange={checkedHandleFormChanges}
onKeyDown={props.handleKeyDown}
disabled={props.addingOrEditingCGDSStudy}
- placeholder='Name'
+ placeholder={intl.formatMessage({ id: 'common.name' })}
maxLength={150}
/>
@@ -71,7 +73,7 @@ export const NewCGDSStudyForm = (props: NewCGDSStudyFormProps) => {
onChange={(_, { name, value }) => props.handleFormChanges(name, value)}
onKeyDown={props.handleKeyDown}
disabled={props.addingOrEditingCGDSStudy}
- placeholder='Description'
+ placeholder={intl.formatMessage({ id: 'common.description' })}
/>
{/* URL */}
@@ -84,7 +86,7 @@ export const NewCGDSStudyForm = (props: NewCGDSStudyFormProps) => {
onChange={checkedHandleFormChanges}
onKeyDown={props.handleKeyDown}
disabled={props.addingOrEditingCGDSStudy}
- placeholder='URL (tar.gz/zip)'
+ placeholder={intl.formatMessage({ id: 'cgdsStudyForm.url.placeholder' })}
maxLength={300}
/>
@@ -97,7 +99,7 @@ export const NewCGDSStudyForm = (props: NewCGDSStudyFormProps) => {
onChange={checkedHandleFormChanges}
onKeyDown={props.handleKeyDown}
disabled={props.addingOrEditingCGDSStudy}
- placeholder='URL of extra info'
+ placeholder={intl.formatMessage({ id: 'cgdsStudyForm.urlInfo.placeholder' })}
maxLength={300}
/>
@@ -106,7 +108,7 @@ export const NewCGDSStudyForm = (props: NewCGDSStudyFormProps) => {
{/* Dataset */}
- CGDS Datasets
+ {intl.formatMessage({ id: 'cgdsStudyForm.datasets.header' })}
{/* mRNA Dataset */}
@@ -151,7 +153,7 @@ export const NewCGDSStudyForm = (props: NewCGDSStudyFormProps) => {
{/* Methylation Dataset */}
{
{/* Clinical Patients Dataset */}
{
{/* Clinical Samples Dataset */}
{
/>
- Required field
+ {intl.formatMessage({ id: 'cgdsStudyForm.requiredField' })}
- In order to have the data available, you must perform the synchronization at least once
+ {intl.formatMessage({ id: 'cgdsStudyForm.syncWarning' })}
{/* Submit form button */}
{
{/* Cancel button */}
void,
@@ -11,6 +12,7 @@ interface Props {
export const EditIcon = (props: Props) => {
const currentUser = useContext(CurrentUserContext)
+ const intl = useIntl()
if (props.ownerId !== currentUser?.id) {
return <>>
@@ -21,7 +23,7 @@ export const EditIcon = (props: Props) => {
name='pencil'
className='clickable margin-left-5'
color='yellow'
- title='Edit'
+ title={intl.formatMessage({ id: 'common.edit' })}
onClick={props.editExperiment}
disabled={props.disabled}
/>
diff --git a/src/frontend/static/frontend/src/components/common/PaginatedTable.tsx b/src/frontend/static/frontend/src/components/common/PaginatedTable.tsx
index 12b8d416..ff2f134d 100644
--- a/src/frontend/static/frontend/src/components/common/PaginatedTable.tsx
+++ b/src/frontend/static/frontend/src/components/common/PaginatedTable.tsx
@@ -113,6 +113,7 @@ interface PaginatedTableProps {
entriesSelectWidth?: SemanticWIDTHS,
/** Callback to render custom components applied to data retrieved from backend API */
mapFunction: (elem: T) => ReactElement
+ intl: IntlShape
}
/**
@@ -442,6 +443,7 @@ class PaginatedTable extends React.Component, Paginate
}
render () {
+ const { intl } = this.props
const tableControl = this.state.tableControl
// Applies map function
@@ -470,7 +472,7 @@ class PaginatedTable extends React.Component, Paginate
- Loading...
+ {intl.formatMessage({ id: 'paginatedTable.loading' })}
@@ -507,7 +509,7 @@ class PaginatedTable extends React.Component, Paginate
extends React.Component, Paginate
{customFilters}
{/* Page size */}
extends React.Component, Paginate
}
}
-export { PaginatedTable, DefaultSortProp, PaginationCustomFilter }
+const PaginatedTableWithIntl = (props: Omit, 'intl'>) => {
+ const intl = useIntl()
+ return
+}
+
+export { PaginatedTableWithIntl as PaginatedTable, DefaultSortProp, PaginationCustomFilter }
diff --git a/src/frontend/static/frontend/src/components/common/SourceSelectors.tsx b/src/frontend/static/frontend/src/components/common/SourceSelectors.tsx
index 08ee3cc3..2f37e39e 100644
--- a/src/frontend/static/frontend/src/components/common/SourceSelectors.tsx
+++ b/src/frontend/static/frontend/src/components/common/SourceSelectors.tsx
@@ -4,6 +4,7 @@ import { DjangoCGDSStudy, DjangoUserFile } from '../../utils/django_interfaces'
import { SourceType, FileType, Source } from '../../utils/interfaces'
import { SourceForm } from '../pipeline/SourceForm'
import { Grid } from 'semantic-ui-react'
+import { useIntl } from 'react-intl'
/** Structure to handle a Source in this component. */
type SourceFormData = {
@@ -41,6 +42,7 @@ interface SourceSelectorsProps {
* @returns Component.
*/
export const SourceSelectors = (props: SourceSelectorsProps) => {
+ const intl = useIntl()
const {
handleChangeSourceType,
selectNewFile,
@@ -53,10 +55,10 @@ export const SourceSelectors = (props: SourceSelectorsProps) => {
- {props.clinicalSource !== undefined && (
+ {props.clinicalSource !== undefined && (
{
selectStudy={(selectedStudy) => {
selectStudy(selectedStudy, 'clinicalSource')
}}
- />
+ />
)}
{/* mRNA */}
- {props.mRNASource !== undefined && (
+ {props.mRNASource !== undefined && (
{
selectStudy={(selectedStudy) => {
selectStudy(selectedStudy, 'mRNASource')
}}
- />
+ />
)}
{/* miRNA */}
- {props.mirnaSource !== undefined && (
+ {props.mirnaSource !== undefined && (
{
selectStudy={(selectedStudy) => {
selectStudy(selectedStudy, 'mirnaSource')
}}
- />
+ />
)}
{/* CNA */}
- {props.cnaSource !== undefined && (
+ {props.cnaSource !== undefined && (
{
selectStudy={(selectedStudy) => {
selectStudy(selectedStudy, 'cnaSource')
}}
- />
+ />
)}
{/* Methylation */}
- {props.methylationSource !== undefined && (
+ {props.methylationSource !== undefined && (
{
selectStudy={(selectedStudy) => {
selectStudy(selectedStudy, 'methylationSource')
}}
- />
+ />
)}
diff --git a/src/frontend/static/frontend/src/components/common/SwitchPublicButton.tsx b/src/frontend/static/frontend/src/components/common/SwitchPublicButton.tsx
index a09ae96a..fb7f4025 100644
--- a/src/frontend/static/frontend/src/components/common/SwitchPublicButton.tsx
+++ b/src/frontend/static/frontend/src/components/common/SwitchPublicButton.tsx
@@ -3,6 +3,7 @@ import { Icon } from 'semantic-ui-react'
import { CurrentUserContext } from '../Base'
import { getDjangoHeader } from '../../utils/util_functions'
import ky from 'ky'
+import { useIntl } from 'react-intl'
declare const urlPostSwitchPublicView
@@ -21,6 +22,12 @@ interface Props {
export const SwitchPublicButton = (props: Props) => {
const currentUser = useContext(CurrentUserContext)
const [isLoading, setIsLoading] = useState(false)
+ const intl = useIntl()
+
+ const makePrivateText = intl.formatMessage({ id: 'switchPublicButton.makePrivate' }, { nameEntity: props.nameEntity })
+ const makePublicText = intl.formatMessage({ id: 'switchPublicButton.makePublic' }, { nameEntity: props.nameEntity })
+ const confirmMakePrivateText = intl.formatMessage({ id: 'switchPublicButton.confirmMakePrivate' }, { nameEntity: props.nameEntity })
+ const confirmMakePublicText = intl.formatMessage({ id: 'switchPublicButton.confirmMakePublic' }, { nameEntity: props.nameEntity })
/**
* Function to switch visibility of experiment
@@ -56,8 +63,11 @@ export const SwitchPublicButton = (props: Props) => {
className='clickable margin-left-5'
disabled={isLoading}
color={props.publicButtonEntity.is_public ? 'red' : 'teal'}
- title={props.publicButtonEntity.is_public ? `Make ${props.nameEntity} private` : `Make ${props.nameEntity} public`}
- onClick={() => props.handleChangeConfirmModalState(true, props.publicButtonEntity.is_public ? `Make ${props.nameEntity} private` : `Make ${props.nameEntity} public`, props.publicButtonEntity.is_public ? `Are you sure to make the ${props.nameEntity} private?` : `Are you sure to make the ${props.nameEntity} public`, handleSwitchVisibility)}
+ title={props.publicButtonEntity.is_public ? makePrivateText : makePublicText}
+ onClick={() => props.handleChangeConfirmModalState(true,
+ props.publicButtonEntity.is_public ? makePrivateText : makePublicText,
+ props.publicButtonEntity.is_public ? confirmMakePrivateText : confirmMakePublicText,
+ handleSwitchVisibility)}
/>
)
}
diff --git a/src/frontend/static/frontend/src/components/common/TableCellSources.tsx b/src/frontend/static/frontend/src/components/common/TableCellSources.tsx
index 88c614da..36817201 100644
--- a/src/frontend/static/frontend/src/components/common/TableCellSources.tsx
+++ b/src/frontend/static/frontend/src/components/common/TableCellSources.tsx
@@ -2,6 +2,7 @@ import React from 'react'
import { SourcePopup } from '../pipeline/all-experiments-view/SourcePopup'
import { DjangoExperimentSource } from '../../utils/django_interfaces'
import { GenesColors, Nullable } from '../../utils/interfaces'
+import { useIntl } from 'react-intl'
/**
* Component to show sourcePopups if files provides
@@ -16,6 +17,7 @@ interface Props {
}
export const TableCellSources = (props: Props) => {
+ const intl = useIntl()
return (
<>
{
@@ -25,7 +27,7 @@ export const TableCellSources = (props: Props) => {
source={props.clinical_source}
iconName='file'
iconColor={GenesColors.CLINICAL}
- downloadButtonTitle='Download source clinical file'
+ downloadButtonTitle={intl.formatMessage({ id: 'tableCellSources.downloadClinical' })}
/>
)
}
@@ -36,7 +38,7 @@ export const TableCellSources = (props: Props) => {
source={props.mrna_source}
iconName='file alternate'
iconColor={GenesColors.MRNA}
- downloadButtonTitle='Download source mRna file'
+ downloadButtonTitle={intl.formatMessage({ id: 'tableCellSources.downloadMrna' })}
/>
)
}
@@ -47,7 +49,7 @@ export const TableCellSources = (props: Props) => {
source={props.mirna_source}
iconName='file alternate'
iconColor={GenesColors.MIRNA}
- downloadButtonTitle='Download source mirna file'
+ downloadButtonTitle={intl.formatMessage({ id: 'tableCellSources.downloadMirna' })}
/>
)
}
@@ -58,7 +60,7 @@ export const TableCellSources = (props: Props) => {
source={props.cna_source}
iconName='file alternate'
iconColor={GenesColors.CNA}
- downloadButtonTitle='Download source cna file'
+ downloadButtonTitle={intl.formatMessage({ id: 'tableCellSources.downloadCna' })}
/>
)
}
@@ -69,7 +71,7 @@ export const TableCellSources = (props: Props) => {
source={props.methylation_source}
iconName='file alternate'
iconColor={GenesColors.METHYLATION}
- downloadButtonTitle='Download source methylation file'
+ downloadButtonTitle={intl.formatMessage({ id: 'tableCellSources.downloadMethylation' })}
/>
)
}
diff --git a/src/frontend/static/frontend/src/components/common/TagForm.tsx b/src/frontend/static/frontend/src/components/common/TagForm.tsx
index 27b66977..1bee84d1 100644
--- a/src/frontend/static/frontend/src/components/common/TagForm.tsx
+++ b/src/frontend/static/frontend/src/components/common/TagForm.tsx
@@ -2,6 +2,7 @@ import React from 'react'
import { Input } from 'semantic-ui-react'
import { DjangoTag } from '../../utils/django_interfaces'
import { checkedValidityCallback } from '../../utils/util_functions'
+import { useIntl } from 'react-intl'
/**
* Component's props
@@ -20,6 +21,7 @@ interface TagFormProps {
* @returns Component
*/
export const TagForm = (props: TagFormProps) => {
+ const intl = useIntl()
const checkedHandleFormChanges = checkedValidityCallback(props.onHandleAddTagInputsChange)
return (
@@ -34,7 +36,7 @@ export const TagForm = (props: TagFormProps) => {
onKeyDown={props.onHandleKeyDown}
loading={props.loading}
disabled={props.disableInputs}
- placeholder='New tag'
+ placeholder={intl.formatMessage({ id: 'tagForm.newTag' })}
maxLength={20}
/>
@@ -46,7 +48,7 @@ export const TagForm = (props: TagFormProps) => {
onChange={checkedHandleFormChanges}
onKeyDown={props.onHandleKeyDown}
disabled={props.disableInputs}
- placeholder='Description (optional)'
+ placeholder={intl.formatMessage({ id: 'common.descriptionOptional' })}
maxLength={60}
/>
diff --git a/src/frontend/static/frontend/src/components/common/TagLabel.tsx b/src/frontend/static/frontend/src/components/common/TagLabel.tsx
index 26ef3ae2..559019db 100644
--- a/src/frontend/static/frontend/src/components/common/TagLabel.tsx
+++ b/src/frontend/static/frontend/src/components/common/TagLabel.tsx
@@ -3,6 +3,7 @@ import { Label } from 'semantic-ui-react'
import { DjangoTag } from '../../utils/django_interfaces'
import { SemanticSIZES } from 'semantic-ui-react/dist/commonjs/generic'
import { Nullable } from '../../utils/interfaces'
+import { useIntl } from 'react-intl'
/** TagLabel props. */
interface TagLabelProps {
@@ -18,14 +19,18 @@ interface TagLabelProps {
* @param props Component's props.
* @returns Component.
*/
-export const TagLabel = (props: TagLabelProps) => (
-
- {props.tag ? props.tag.name : 'No tag assigned'}
-
-)
+export const TagLabel = (props: TagLabelProps) => {
+ const intl = useIntl()
+
+ return (
+
+ {props.tag ? props.tag.name : intl.formatMessage({ id: 'tagLabel.noTagAssigned' })}
+
+ )
+}
diff --git a/src/frontend/static/frontend/src/components/common/TryAgainSegment.tsx b/src/frontend/static/frontend/src/components/common/TryAgainSegment.tsx
index 5fff5ce5..72560bc5 100644
--- a/src/frontend/static/frontend/src/components/common/TryAgainSegment.tsx
+++ b/src/frontend/static/frontend/src/components/common/TryAgainSegment.tsx
@@ -1,5 +1,6 @@
import React from 'react'
import { Button, Header, Icon, Segment } from 'semantic-ui-react'
+import { useIntl } from 'react-intl'
/** Component's props. */
interface TryAgainSegmentProps {
@@ -12,17 +13,21 @@ interface TryAgainSegmentProps {
* @param props Component's props.
* @returns Component.
*/
-export const TryAgainSegment = (props: TryAgainSegmentProps) => (
-
-
-
- Something went wrong, please try again
-
+export const TryAgainSegment = (props: TryAgainSegmentProps) => {
+ const intl = useIntl()
-
-
- Try Again
-
-
-
-)
+ return (
+
+
+
+ {intl.formatMessage({ id: 'tryAgainSegment.message' })}
+
+
+
+
+ {intl.formatMessage({ id: 'tryAgainSegment.button' })}
+
+
+
+ )
+}
diff --git a/src/frontend/static/frontend/src/components/common/boxplots/BoxplotsCommons.tsx b/src/frontend/static/frontend/src/components/common/boxplots/BoxplotsCommons.tsx
index f97075fe..cb7dcca4 100644
--- a/src/frontend/static/frontend/src/components/common/boxplots/BoxplotsCommons.tsx
+++ b/src/frontend/static/frontend/src/components/common/boxplots/BoxplotsCommons.tsx
@@ -1,6 +1,7 @@
import React from 'react'
/* import { XYChart, theme, withParentSize, withTheme } from '@data-ui/xy-chart' */
import { DjangoSourceDataOutliersBasic } from '../../../utils/django_interfaces'
+import { useIntl } from 'react-intl'
/** Type of BoxPlot datum field */
type BoxplotDatum = {
@@ -83,9 +84,10 @@ const TooltipElement = (props: TooltipElementProps) => (
* @param props Component's props
* @returns Component
*/
-const renderBoxPlotTooltip = (props: BoxPlotTooltipProps) => {
+const RenderBoxPlotTooltip = (props: BoxPlotTooltipProps) => {
const { min, max, mean, median, firstQuartile, thirdQuartile, outliers, outliersObjects, cnaDescription } = props.datum
const color = props.color
+ const intl = useIntl()
return (
@@ -95,15 +97,15 @@ const renderBoxPlotTooltip = (props: BoxPlotTooltipProps) => {
>
)}
-
-
-
-
-
-
+
+
+
+
+
+
{outliers && outliers.length > 0 && (
<>
-
+
{outliersObjects.map((outlier) => (
{
const [showNewClusterLabelsSet, setShowNewClusterLabelsSet] = useState(false)
-
+ const intl = useIntl()
// TODO: show this in the TrainedModels page
return (
@@ -48,27 +49,27 @@ export const ClusterLabelsSetsModal = (props: ClusterLabelsSetsModalProps) => {
>
- Cluster labels sets
+ {intl.formatMessage({ id: 'clusterLabelsSetsModal.header' })}
- headerTitle='Cluster labels sets'
+ headerTitle={intl.formatMessage({ id: 'clusterLabelsSetsModal.header' })}
headers={[
- { name: 'Name', serverCodeToSort: 'name', width: 3 },
- { name: 'Description', serverCodeToSort: 'description', width: 4 },
- { name: 'Actions' }
+ { name: intl.formatMessage({ id: 'common.name' }), serverCodeToSort: 'name', width: 3 },
+ { name: intl.formatMessage({ id: 'common.description' }), serverCodeToSort: 'description', width: 4 },
+ { name: intl.formatMessage({ id: 'common.actions' }) }
]}
queryParams={{ trained_model_pk: props.trainedModelPk }}
customElements={[
-
+
{ setShowNewClusterLabelsSet(true) }}>
]}
showSearchInput
- searchLabel='Name'
- searchPlaceholder='Search by name or description'
+ searchLabel={intl.formatMessage({ id: 'common.name' })}
+ searchPlaceholder={intl.formatMessage({ id: 'clusterLabelsSetsModal.searchPlaceholder' })}
urlToRetrieveData={urlClusterLabelsSetsPaginated}
// updateWSKey='update_trained_models' // TODO: implement
mapFunction={(clusterLabelsSet: ClusterLabelsSet) => {
@@ -83,7 +84,7 @@ export const ClusterLabelsSetsModal = (props: ClusterLabelsSetsModalProps) => {
name='pencil'
color='yellow'
className='clickable'
- title='Edit'
+ title={intl.formatMessage({ id: 'common.edit' })}
// onClick={() => setShowNewClusterLabelsSet(clusterLabelsSet)}
/> */}
diff --git a/src/frontend/static/frontend/src/components/common/cluster-labels/ClusterLabelsSetSelect.tsx b/src/frontend/static/frontend/src/components/common/cluster-labels/ClusterLabelsSetSelect.tsx
index ca7b6b96..e1774e02 100644
--- a/src/frontend/static/frontend/src/components/common/cluster-labels/ClusterLabelsSetSelect.tsx
+++ b/src/frontend/static/frontend/src/components/common/cluster-labels/ClusterLabelsSetSelect.tsx
@@ -5,6 +5,7 @@ import ky from 'ky'
import { alertGeneralError } from '../../../utils/util_functions'
import { InputLabel } from '../InputLabel'
import { WebsocketClientCustom } from '../../../websockets/WebsocketClient'
+import { useIntl } from 'react-intl'
declare const currentUserId: string
declare const urlClusterLabelsSets: string
@@ -29,6 +30,7 @@ export const ClusterLabelsSetSelect = (props: ClusterLabelsSetSelectProps) => {
const [clusterLabelsSets, setClusterLabelsSets] = useState([])
const [loading, setLoading] = useState(false)
const websocketClient = useRef()
+ const intl = useIntl()
useEffect(() => {
// Gets data
@@ -80,7 +82,7 @@ export const ClusterLabelsSetSelect = (props: ClusterLabelsSetSelectProps) => {
return (
<>
-
+
{
clearable
value={props.selectedClusterSetPk}
onChange={(_, { value }) => { props.setSelectedClusterSetPk(value as number | undefined) }}
- placeholder='Use cluster labels'
+ placeholder={intl.formatMessage({ id: 'clusterLabelsSetSelect.placeholder' })}
className='margin-top-2'
disabled={options.length === 0}
/>
diff --git a/src/frontend/static/frontend/src/components/common/cluster-labels/NewClusterLabelsSetModal.tsx b/src/frontend/static/frontend/src/components/common/cluster-labels/NewClusterLabelsSetModal.tsx
index c5d66f0a..4e5f685d 100644
--- a/src/frontend/static/frontend/src/components/common/cluster-labels/NewClusterLabelsSetModal.tsx
+++ b/src/frontend/static/frontend/src/components/common/cluster-labels/NewClusterLabelsSetModal.tsx
@@ -5,6 +5,7 @@ import { HexAlphaColorPicker } from 'react-colorful'
import { alertGeneralError, getDjangoHeader } from '../../../utils/util_functions'
import ky from 'ky'
import { InputLabel } from '../InputLabel'
+import { useIntl } from 'react-intl'
declare const urlClusterLabelsSets: string
@@ -28,6 +29,7 @@ const getDefaultClusterLabelsSet = (trainedModelPk: number): ClusterLabelsSet =>
export const NewClusterLabelsSetModal = (props: NewClusterLabelsSetModalProps) => {
const [newClusterLabelsSet, setNewClusterLabelsSet] = useState(getDefaultClusterLabelsSet(props.trainedModelPk))
const [sendingData, setSendingData] = useState(false)
+ const intl = useIntl()
/** Resets the form when closes the modal. */
useEffect(() => {
@@ -149,26 +151,26 @@ export const NewClusterLabelsSetModal = (props: NewClusterLabelsSetModalProps) =
>
- New Cluster labels sets
+ {intl.formatMessage({ id: 'newClusterLabelsSetModal.header' })}
-
+ {intl.formatMessage({ id: 'newClusterLabelsSetModal.header' })}
handleChanges(name, value)}
/>
handleChanges(name, value)}
/>
@@ -184,8 +186,8 @@ export const NewClusterLabelsSetModal = (props: NewClusterLabelsSetModalProps) =
- Required field
+ {intl.formatMessage({ id: 'common.requiredField' })}
@@ -214,13 +216,13 @@ export const NewClusterLabelsSetModal = (props: NewClusterLabelsSetModalProps) =
fluid
onClick={() => { removeLabel(idx) }}
>
- Delete label
+ {intl.formatMessage({ id: 'newClusterLabelsSetModal.deleteLabel' })}
{/* Color */}
-
+
{ handleChangesLabel(idx, 'color', color) }} />
@@ -229,7 +231,7 @@ export const NewClusterLabelsSetModal = (props: NewClusterLabelsSetModalProps) =
))}
- Add label
+ {intl.formatMessage({ id: 'newClusterLabelsSetModal.addLabel' })}
@@ -240,7 +242,7 @@ export const NewClusterLabelsSetModal = (props: NewClusterLabelsSetModalProps) =
color='red'
onClick={() => props.setShowNewClusterLabelsSet(false)}
>
- Cancel
+ {intl.formatMessage({ id: 'common.cancel' })}
- Confirm
+ {intl.formatMessage({ id: 'common.confirm' })}
diff --git a/src/frontend/static/frontend/src/components/common/prediction-range-label/NewPredictionRangeLabelsSetModal.tsx b/src/frontend/static/frontend/src/components/common/prediction-range-label/NewPredictionRangeLabelsSetModal.tsx
index 18337f82..8f4da197 100644
--- a/src/frontend/static/frontend/src/components/common/prediction-range-label/NewPredictionRangeLabelsSetModal.tsx
+++ b/src/frontend/static/frontend/src/components/common/prediction-range-label/NewPredictionRangeLabelsSetModal.tsx
@@ -6,6 +6,7 @@ import { alertGeneralError, getDjangoHeader } from '../../../utils/util_function
import ky from 'ky'
import { Nullable } from '../../../utils/interfaces'
import { InputLabel } from '../InputLabel'
+import { useIntl } from 'react-intl'
declare const urlPredictionRangeLabelsSets: string
@@ -37,6 +38,7 @@ const getDefaultPredictionRangeLabelsSet = (trainedModelPk: number): PredictionR
export const NewPredictionRangeLabelsSetModal = (props: NewPredictionRangeLabelsSetModalProps) => {
const [newPredictionRangeLabelsSet, setNewPredictionRangeLabelsSet] = useState(getDefaultPredictionRangeLabelsSet(props.trainedModelPk))
const [sendingData, setSendingData] = useState(false)
+ const intl = useIntl()
/** Resets the form when closes the modal. */
useEffect(() => {
@@ -135,14 +137,14 @@ export const NewPredictionRangeLabelsSetModal = (props: NewPredictionRangeLabels
let input: Input = null
if (label.max_value !== null && label.max_value <= label.min_value) {
- msg = 'Max value must be greater than min value'
+ msg = intl.formatMessage({ id: 'newPredictionRangeLabelsSetModal.error.maxValue' })
input = 'max_value'
} else {
const overlapIdx = newPredictionRangeLabelsSet.labels.findIndex((label2) => label2 !== label && (label.max_value === null || (label.max_value !== null && label2.min_value <= label.max_value && label2.max_value as number >= label.min_value)))
if (overlapIdx !== -1) {
const overlapObject = newPredictionRangeLabelsSet.labels[overlapIdx]
- msg = `Ranges overlaps with label "${overlapObject.label}" (position ${overlapIdx + 1})`
+ msg = intl.formatMessage({ id: 'newPredictionRangeLabelsSetModal.error.overlap' }, { label: overlapObject.label, position: overlapIdx + 1 })
input = 'label'
}
}
@@ -174,26 +176,26 @@ export const NewPredictionRangeLabelsSetModal = (props: NewPredictionRangeLabels
>
- New Cluster labels sets
+ {intl.formatMessage({ id: 'newPredictionRangeLabelsSetModal.header' })}
- New PredictionRangeLabelsSet
+ {intl.formatMessage({ id: 'newPredictionRangeLabelsSetModal.subHeader' })}
handleChanges(name, value)}
/>
handleChanges(name, value)}
/>
@@ -201,7 +203,7 @@ export const NewPredictionRangeLabelsSetModal = (props: NewPredictionRangeLabels
{/* List of labels */}
-
+ {intl.formatMessage({ id: 'newPredictionRangeLabelsSetModal.labelsHeader' })}
{newPredictionRangeLabelsSet.labels.map((label, idx) => {
const errorMsg = errorMessages[idx]
@@ -211,8 +213,8 @@ export const NewPredictionRangeLabelsSetModal = (props: NewPredictionRangeLabels
- Required field
+ {intl.formatMessage({ id: 'common.requiredField' })}
@@ -253,13 +255,13 @@ export const NewPredictionRangeLabelsSetModal = (props: NewPredictionRangeLabels
fluid
onClick={() => { removeLabel(idx) }}
>
- Delete label
+ {intl.formatMessage({ id: 'newPredictionRangeLabelsSetModal.deleteLabel' })}
{/* Color */}
-
+
{ handleChangesLabel(idx, 'color', color) }} />
@@ -269,7 +271,7 @@ export const NewPredictionRangeLabelsSetModal = (props: NewPredictionRangeLabels
)
})}
- Add label
+ {intl.formatMessage({ id: 'newPredictionRangeLabelsSetModal.addLabel' })}
@@ -280,7 +282,7 @@ export const NewPredictionRangeLabelsSetModal = (props: NewPredictionRangeLabels
color='red'
onClick={() => props.setShowNewPredictionRangeLabelsSet(false)}
>
- Cancel
+ {intl.formatMessage({ id: 'common.cancel' })}
- Confirm
+ {intl.formatMessage({ id: 'common.confirm' })}
diff --git a/src/frontend/static/frontend/src/components/common/prediction-range-label/PredictionRangeLabelsSetModal.tsx b/src/frontend/static/frontend/src/components/common/prediction-range-label/PredictionRangeLabelsSetModal.tsx
index 78bca22b..183e12c0 100644
--- a/src/frontend/static/frontend/src/components/common/prediction-range-label/PredictionRangeLabelsSetModal.tsx
+++ b/src/frontend/static/frontend/src/components/common/prediction-range-label/PredictionRangeLabelsSetModal.tsx
@@ -4,6 +4,7 @@ import { Button, Form, Icon, Modal, Table } from 'semantic-ui-react'
import { TableCellWithTitle } from '../../common/TableCellWithTitle'
import { ClusterLabelsSet } from '../../biomarkers/types'
import { NewPredictionRangeLabelsSetModal } from './NewPredictionRangeLabelsSetModal'
+import { useIntl } from 'react-intl'
declare const urlPredictionRangeLabelsSetsPaginated: string
@@ -23,6 +24,7 @@ interface PredictionRangeLabelsSetModalProps {
*/
export const PredictionRangeLabelsSetModal = (props: PredictionRangeLabelsSetModalProps) => {
const [showNewPredictionRangeLabelsSet, setShowNewPredictionRangeLabelsSet] = useState(false)
+ const intl = useIntl()
// TODO: show this in the TrainedModels page
@@ -48,27 +50,27 @@ export const PredictionRangeLabelsSetModal = (props: PredictionRangeLabelsSetMod
>
{/* TODO: change the icon */}
- Prediction range labels sets
+ {intl.formatMessage({ id: 'predictionRangeLabelsSetModal.header' })}
- headerTitle='Prediction range labels sets'
+ headerTitle={intl.formatMessage({ id: 'predictionRangeLabelsSetModal.header' })}
headers={[
- { name: 'Name', serverCodeToSort: 'name', width: 3 },
- { name: 'Description', serverCodeToSort: 'description', width: 4 },
- { name: 'Actions' }
+ { name: intl.formatMessage({ id: 'common.name' }), serverCodeToSort: 'name', width: 3 },
+ { name: intl.formatMessage({ id: 'common.description' }), serverCodeToSort: 'description', width: 4 },
+ { name: intl.formatMessage({ id: 'common.actions' }) }
]}
queryParams={{ trained_model_pk: props.trainedModelPk }}
customElements={[
-
+
{ setShowNewPredictionRangeLabelsSet(true) }}>
]}
showSearchInput
- searchLabel='Name'
- searchPlaceholder='Search by name or description'
+ searchLabel={intl.formatMessage({ id: 'common.name' })}
+ searchPlaceholder={intl.formatMessage({ id: 'predictionRangeLabelsSetModal.searchPlaceholder' })}
urlToRetrieveData={urlPredictionRangeLabelsSetsPaginated}
// updateWSKey='update_trained_models' // TODO: implement
mapFunction={(clusterLabelsSet: ClusterLabelsSet) => {
@@ -83,7 +85,7 @@ export const PredictionRangeLabelsSetModal = (props: PredictionRangeLabelsSetMod
name='pencil'
color='yellow'
className='clickable'
- title='Edit'
+ title={intl.formatMessage({ id: 'common.edit' })}
// onClick={() => setShowNewClusterLabelsSet(clusterLabelsSet)}
/> */}
diff --git a/src/frontend/static/frontend/src/components/common/prediction-range-label/PredictionRangeLabelsSetSelect.tsx b/src/frontend/static/frontend/src/components/common/prediction-range-label/PredictionRangeLabelsSetSelect.tsx
index 08d0284f..c2c5aaa7 100644
--- a/src/frontend/static/frontend/src/components/common/prediction-range-label/PredictionRangeLabelsSetSelect.tsx
+++ b/src/frontend/static/frontend/src/components/common/prediction-range-label/PredictionRangeLabelsSetSelect.tsx
@@ -1,88 +1,90 @@
-import React, { useEffect, useRef, useState } from 'react'
-import { Select, DropdownItemProps } from 'semantic-ui-react'
-import { PredictionRangeLabelsSet } from '../../biomarkers/types'
-import ky from 'ky'
-import { alertGeneralError } from '../../../utils/util_functions'
-import { InputLabel } from '../InputLabel'
-
-declare const urlPredictionRangeLabelsSets: string
-
-/** PredictionRangeLabelsSetSelect props. */
-interface PredictionRangeLabelsSetSelectProps {
- /** TrainedModel primary key. */
- trainedModelPk: number,
- /** Selected PredictionRangeLabelsSet primary key. */
- selectedClusterSetPk: number | undefined,
- /** Function to set the selected PredictionRangeLabelsSet primary key. */
- setSelectedClusterSetPk: (newValue: number | undefined) => void
-}
-
-/**
- * Renders a Select for Cluster labels set (Django PredictionRangeLabelsSet model)
- * @param props Component props.
- * @returns Component.
- */
-export const PredictionRangeLabelsSetSelect = (props: PredictionRangeLabelsSetSelectProps) => {
- const abortController = useRef(new AbortController())
- const [predictionRangeLabelsSets, setPredictionRangeLabelsSets] = useState([])
- const [loading, setLoading] = useState(false)
-
- useEffect(() => {
- getData()
- }, [])
-
- /** Retrieves all the PredictionRangeLabelsSet instances for this user and the TrainedModel */
- function getData () {
- setLoading(true)
-
- const searchParams = { trained_model_pk: props.trainedModelPk }
- ky.get(urlPredictionRangeLabelsSets, { searchParams, signal: abortController?.current.signal }).then((response) => {
- response.json().then((predictionRangeLabelsSetData) => {
- setPredictionRangeLabelsSets(predictionRangeLabelsSetData)
- }).catch((err) => {
- alertGeneralError()
- console.log('Error parsing JSON ->', err)
- })
- }).catch((err) => {
- if (!abortController?.current.signal.aborted) {
- alertGeneralError()
- }
-
- console.log('Error getting model PredictionRangeLabelsSets', err)
- }).finally(() => {
- if (!abortController?.current.signal.aborted) {
- setLoading(false)
- }
- })
- }
-
- const options: DropdownItemProps[] = predictionRangeLabelsSets.map((predictionRangeLabelsSet) => (
- { key: predictionRangeLabelsSet.id, text: predictionRangeLabelsSet.name, value: predictionRangeLabelsSet.id }
- ))
- useEffect(() => {
- return () => {
- // Cleanup: cancel the ongoing request when component unmounts
- abortController.current.abort()
- }
- }, [])
-
- return (
- <>
-
-
- { props.setSelectedClusterSetPk(value as number | undefined) }}
- placeholder='Use range labels'
- className='margin-top-2'
- disabled={options.length === 0}
- />
- >
- )
-}
+import React, { useEffect, useRef, useState } from 'react'
+import { Select, DropdownItemProps } from 'semantic-ui-react'
+import { PredictionRangeLabelsSet } from '../../biomarkers/types'
+import ky from 'ky'
+import { alertGeneralError } from '../../../utils/util_functions'
+import { InputLabel } from '../InputLabel'
+import { useIntl } from 'react-intl'
+
+declare const urlPredictionRangeLabelsSets: string
+
+/** PredictionRangeLabelsSetSelect props. */
+interface PredictionRangeLabelsSetSelectProps {
+ /** TrainedModel primary key. */
+ trainedModelPk: number,
+ /** Selected PredictionRangeLabelsSet primary key. */
+ selectedClusterSetPk: number | undefined,
+ /** Function to set the selected PredictionRangeLabelsSet primary key. */
+ setSelectedClusterSetPk: (newValue: number | undefined) => void
+}
+
+/**
+ * Renders a Select for Cluster labels set (Django PredictionRangeLabelsSet model)
+ * @param props Component props.
+ * @returns Component.
+ */
+export const PredictionRangeLabelsSetSelect = (props: PredictionRangeLabelsSetSelectProps) => {
+ const abortController = useRef(new AbortController())
+ const [predictionRangeLabelsSets, setPredictionRangeLabelsSets] = useState([])
+ const [loading, setLoading] = useState(false)
+ const intl = useIntl()
+
+ useEffect(() => {
+ getData()
+ }, [])
+
+ /** Retrieves all the PredictionRangeLabelsSet instances for this user and the TrainedModel */
+ function getData () {
+ setLoading(true)
+
+ const searchParams = { trained_model_pk: props.trainedModelPk }
+ ky.get(urlPredictionRangeLabelsSets, { searchParams, signal: abortController?.current.signal }).then((response) => {
+ response.json().then((predictionRangeLabelsSetData) => {
+ setPredictionRangeLabelsSets(predictionRangeLabelsSetData)
+ }).catch((err) => {
+ alertGeneralError()
+ console.log('Error parsing JSON ->', err)
+ })
+ }).catch((err) => {
+ if (!abortController?.current.signal.aborted) {
+ alertGeneralError()
+ }
+
+ console.log('Error getting model PredictionRangeLabelsSets', err)
+ }).finally(() => {
+ if (!abortController?.current.signal.aborted) {
+ setLoading(false)
+ }
+ })
+ }
+
+ const options: DropdownItemProps[] = predictionRangeLabelsSets.map((predictionRangeLabelsSet) => (
+ { key: predictionRangeLabelsSet.id, text: predictionRangeLabelsSet.name, value: predictionRangeLabelsSet.id }
+ ))
+ useEffect(() => {
+ return () => {
+ // Cleanup: cancel the ongoing request when component unmounts
+ abortController.current.abort()
+ }
+ }, [])
+
+ return (
+ <>
+
+
+ { props.setSelectedClusterSetPk(value as number | undefined) }}
+ placeholder={intl.formatMessage({ id: 'predictionRangeLabelsSetSelect.placeholder' })}
+ className='margin-top-2'
+ disabled={options.length === 0}
+ />
+ >
+ )
+}
diff --git a/src/frontend/static/frontend/src/components/differential-expression/DifferentialExpressionForm.tsx b/src/frontend/static/frontend/src/components/differential-expression/DifferentialExpressionForm.tsx
index 8144b70f..e4b0b91e 100644
--- a/src/frontend/static/frontend/src/components/differential-expression/DifferentialExpressionForm.tsx
+++ b/src/frontend/static/frontend/src/components/differential-expression/DifferentialExpressionForm.tsx
@@ -11,6 +11,7 @@ import { MAX_FILE_SIZE_IN_MB_WARN } from '../../utils/constants'
import { intersection, isEqual } from 'lodash'
import { DifferentialExpressionInputClinicalAttribute } from './DifferentialExpressionInputClinicalAttribute'
import { DifferentialExpressionAnalysis } from './types'
+import { useIntl } from 'react-intl'
// Define the possible field names for number of samples
type NumberOfSamplesFields = 'numberOfSamplesMRNA' | 'numberOfSamplesClinical'
@@ -79,6 +80,7 @@ interface DifferentialExpressionFormProps {
export const DifferentialExpressionForm = (props: DifferentialExpressionFormProps) => {
const [form, setForm] = useState(cleanForm)
const abortController = useRef(new AbortController())
+ const intl = useIntl()
/**
* Change the source state to submit a pipeline
@@ -258,14 +260,14 @@ export const DifferentialExpressionForm = (props: DifferentialExpressionFormProp
ky.patch(urlUpdateExperiment + `/${props.experimentToEdit?.id}/`, { headers: myHeaders, json: body }).then((response) => {
response.json().then(() => {
- props.updateAlert(CustomAlertTypes.SUCCESS, 'Differential Expression experiment updated successfully!')
+ props.updateAlert(CustomAlertTypes.SUCCESS, intl.formatMessage({ id: 'differentialExpressionForm.successUpdated' }))
setForm(cleanForm)
}).catch((err) => {
console.error('Error parsing JSON ->', err)
})
}).catch((err) => {
console.error('Error to update experiment ->', err)
- props.updateAlert(CustomAlertTypes.ERROR, 'Error to update Differential Expression experiment!')
+ props.updateAlert(CustomAlertTypes.ERROR, intl.formatMessage({ id: 'differentialExpressionForm.errorUpdating' }))
}).finally(() => {
setForm(prevState => ({
...prevState,
@@ -297,14 +299,14 @@ export const DifferentialExpressionForm = (props: DifferentialExpressionFormProp
}
ky.post(urlDifferentialExpressionSubmit, { headers: myHeaders, json: body }).then((response) => {
response.json().then(() => {
- props.updateAlert(CustomAlertTypes.SUCCESS, 'Differential Expression experiment created successfully!')
+ props.updateAlert(CustomAlertTypes.SUCCESS, intl.formatMessage({ id: 'differentialExpressionForm.successCreated' }))
setForm(cleanForm)
}).catch((err) => {
console.error('Error parsing JSON ->', err)
})
}).catch((err) => {
console.error('Error getting users ->', err)
- props.updateAlert(CustomAlertTypes.ERROR, 'Error creating Differential Expression experiment!')
+ props.updateAlert(CustomAlertTypes.ERROR, intl.formatMessage({ id: 'differentialExpressionForm.errorCreating' }))
}).finally(() => {
setForm(prevState => ({
...prevState,
@@ -561,7 +563,7 @@ export const DifferentialExpressionForm = (props: DifferentialExpressionFormProp
setForm(prevState => ({
...prevState,
numberOfSamplesMRNA: mRNAHeadersColumnsNames.length,
- numberOfSamplesClinial: clinicalHeadersColumnsNames.length,
+ numberOfSamplesClinical: clinicalHeadersColumnsNames.length,
numberOfSamplesInCommon: intersection(
mRNAHeadersColumnsNames,
clinicalHeadersColumnsNames
@@ -600,13 +602,13 @@ export const DifferentialExpressionForm = (props: DifferentialExpressionFormProp
- New Differential Expression
+ {intl.formatMessage({ id: 'differentialExpressionForm.header' })}
handleChangeForm(e.target.value, 'differentialExpressionName')}
type='text'
- placeholder='Name'
+ placeholder={intl.formatMessage({ id: 'common.name' })}
className='diff--side--bar--container--item--margin'
value={form.differentialExpressionName}
icon='asterisk'
@@ -616,7 +618,7 @@ export const DifferentialExpressionForm = (props: DifferentialExpressionFormProp
style={{ maxWidth: '100%', minWidth: '100%' }}
rows={3}
onChange={(_, e) => handleChangeForm(e.value ? e.value.toString() : '', 'differentialExpressionDescription')}
- placeholder='Description'
+ placeholder={intl.formatMessage({ id: 'common.description' })}
className='diff--side--bar--container--item--margin'
value={form.differentialExpressionDescription}
/>
@@ -624,7 +626,7 @@ export const DifferentialExpressionForm = (props: DifferentialExpressionFormProp
- Samples mRNA: {form.numberOfSamplesMRNA}
- Samples clinical: {form.numberOfSamplesClinical}
- Samples in common: {form.numberOfSamplesInCommon}
+ {intl.formatMessage({ id: 'differentialExpressionForm.samplesMRNA' }, { count: form.numberOfSamplesMRNA })}
+ {intl.formatMessage({ id: 'differentialExpressionForm.samplesClinical' }, { count: form.numberOfSamplesClinical })}
+ {intl.formatMessage({ id: 'differentialExpressionForm.samplesInCommon' }, { count: form.numberOfSamplesInCommon })}
@@ -686,8 +688,8 @@ export const DifferentialExpressionForm = (props: DifferentialExpressionFormProp
{/* Coefficient threshold slider */}{/* Minimum Standard Deviation for Genes */}
@@ -707,8 +709,8 @@ export const DifferentialExpressionForm = (props: DifferentialExpressionFormProp
@@ -728,8 +730,8 @@ export const DifferentialExpressionForm = (props: DifferentialExpressionFormProp
@@ -758,7 +760,7 @@ export const DifferentialExpressionForm = (props: DifferentialExpressionFormProp
color='green'
loading={form.isLoading}
>
- {form.isEditing ? 'Edit experiment' : 'Create experiment'}
+ {form.isEditing ? intl.formatMessage({ id: 'differentialExpressionForm.editExperiment' }) : intl.formatMessage({ id: 'differentialExpressionForm.createExperiment' })}
- {form.isEditing ? 'Cancel edit' : 'Reset form'}
+ {form.isEditing ? intl.formatMessage({ id: 'differentialExpressionForm.cancelEdit' }) : intl.formatMessage({ id: 'differentialExpressionForm.resetForm' })}
)
diff --git a/src/frontend/static/frontend/src/components/differential-expression/DifferentialExpressionInputClinicalAttribute.tsx b/src/frontend/static/frontend/src/components/differential-expression/DifferentialExpressionInputClinicalAttribute.tsx
index b1ff4dc7..7633da07 100644
--- a/src/frontend/static/frontend/src/components/differential-expression/DifferentialExpressionInputClinicalAttribute.tsx
+++ b/src/frontend/static/frontend/src/components/differential-expression/DifferentialExpressionInputClinicalAttribute.tsx
@@ -1,6 +1,7 @@
import React from 'react'
import { Form } from 'semantic-ui-react'
import { InputLabel } from '../common/InputLabel'
+import { useIntl } from 'react-intl'
interface DifferentialExpressionInputClinicalAttributeProps {
/* List of clinical attributes available for selection */
@@ -19,9 +20,11 @@ interface DifferentialExpressionInputClinicalAttributeProps {
* @returns Component.
*/
export const DifferentialExpressionInputClinicalAttribute = (props: DifferentialExpressionInputClinicalAttributeProps) => {
+ const intl = useIntl()
+
return (
<>
-
+
{ props.onChange(value as string) }}
- placeholder='Clinical attribute to group by'
+ placeholder={intl.formatMessage({ id: 'differentialExpressionInputClinicalAttribute.placeholder' })}
disabled={props.isEditing}
/>
>
diff --git a/src/frontend/static/frontend/src/components/differential-expression/DifferentialExpressionModalResults.tsx b/src/frontend/static/frontend/src/components/differential-expression/DifferentialExpressionModalResults.tsx
index dbbebce8..91f3b1c6 100644
--- a/src/frontend/static/frontend/src/components/differential-expression/DifferentialExpressionModalResults.tsx
+++ b/src/frontend/static/frontend/src/components/differential-expression/DifferentialExpressionModalResults.tsx
@@ -3,6 +3,7 @@ import { DifferentialExpressionAnalysis } from './types'
import { Icon, Modal, Tab, TabPane } from 'semantic-ui-react'
import { DifferentialExpressionModalResultsTableView } from './DifferentialExpressionModalResultsTableView'
import { DifferentialExpressionModalResultsVolcanoPlot } from './DifferentialExpressionModalResultsVolcanoPlot'
+import { useIntl } from 'react-intl'
interface DifferentialExpressionModalResultsProps {
/* Whether the results modal is open */
@@ -15,10 +16,11 @@ interface DifferentialExpressionModalResultsProps {
/* Differential expression results modal component */
export const DifferentialExpressionModalResults = (props: DifferentialExpressionModalResultsProps) => {
+ const intl = useIntl()
/* Tab panes for results modal */
const panes = [
{
- menuItem: 'Table',
+ menuItem: intl.formatMessage({ id: 'common.table' }),
render: () => (
@@ -26,7 +28,7 @@ export const DifferentialExpressionModalResults = (props: DifferentialExpression
)
},
{
- menuItem: 'Volcano Plot',
+ menuItem: intl.formatMessage({ id: 'differentialExpressionModalResults.tab.volcanoPlot' }),
render: () => (
@@ -47,7 +49,7 @@ export const DifferentialExpressionModalResults = (props: DifferentialExpression
>
<>
- Differential Expression Analysis Results - {props.differentialExpressionAnalysis?.name}
+ {intl.formatMessage({ id: 'differentialExpressionModalResults.header' }, { name: props.differentialExpressionAnalysis?.name })}
diff --git a/src/frontend/static/frontend/src/components/differential-expression/DifferentialExpressionModalResultsTableView.tsx b/src/frontend/static/frontend/src/components/differential-expression/DifferentialExpressionModalResultsTableView.tsx
index 91093326..6ab54b7b 100644
--- a/src/frontend/static/frontend/src/components/differential-expression/DifferentialExpressionModalResultsTableView.tsx
+++ b/src/frontend/static/frontend/src/components/differential-expression/DifferentialExpressionModalResultsTableView.tsx
@@ -3,6 +3,7 @@ import { Table, Icon, TableCell, Form, Button } from 'semantic-ui-react'
import { PaginatedTable, PaginationCustomFilter } from '../common/PaginatedTable'
import { DiffExpExperimentDetail } from './types'
import { TableCellWithTitle } from '../common/TableCellWithTitle'
+import { useIntl } from 'react-intl'
declare const urlDifferentialExpressionExperimentResults: string
declare const urlDownloadDifferentialExpressionResults: string
@@ -13,6 +14,7 @@ interface DifferentialExpressionModalResultsProps {
export const DifferentialExpressionModalResultsTableView = (props: DifferentialExpressionModalResultsProps) => {
const [pValueFilter, setPValueFilter] = useState(0.05)
const [logFilter, setLogFilter] = useState(1)
+ const intl = useIntl()
const downloadUrl = () => {
const searchParams = new URLSearchParams({
@@ -29,12 +31,12 @@ export const DifferentialExpressionModalResultsTableView = (props: DifferentialE
const customInputs: PaginationCustomFilter[] = [
{
- label: 'Log fold change threshold',
+ label: intl.formatMessage({ id: 'diffExpResultsTable.logFoldThreshold' }),
keyForServer: 'fc_threshold',
defaultValue: 1,
width: 2,
options: [
- { key: 'no_log', text: 'No Log Fold' },
+ { key: 'no_log', text: intl.formatMessage({ id: 'diffExpResultsTable.noLogFold' }) },
{ key: '1', text: '1', value: 1 },
{ key: '2', text: '2', value: 2 },
{ key: '3', text: '3', value: 3 },
@@ -44,12 +46,12 @@ export const DifferentialExpressionModalResultsTableView = (props: DifferentialE
onChangeFilterEvent: (value) => setLogFilter(value),
},
{
- label: 'P-value threshold',
+ label: intl.formatMessage({ id: 'diffExpResultsTable.pValueThreshold' }),
keyForServer: 'p_threshold',
defaultValue: 0.05,
width: 2,
options: [
- { key: 'no_p_val', text: 'No P-value' },
+ { key: 'no_p_val', text: intl.formatMessage({ id: 'diffExpResultsTable.noPValue' }) },
{ key: '0.05', text: '0.05', value: 0.05 },
{ key: '0.01', text: '0.01', value: 0.01 },
],
@@ -60,34 +62,34 @@ export const DifferentialExpressionModalResultsTableView = (props: DifferentialE
return (
<>
- headerTitle='Experiment results'
+ headerTitle={intl.formatMessage({ id: 'diffExpResultsTable.headerTitle' })}
headers={[
- { name: 'Gene', serverCodeToSort: 'gene' },
- { name: 'Adjusted p-value', serverCodeToSort: 'adj_p_val' },
- { name: 'Average expression', serverCodeToSort: 'ave_expr' },
- { name: 'B statistic', serverCodeToSort: 'b_statistic' },
- { name: 'Log Fold Change', serverCodeToSort: 'log_fc' },
- { name: 'P-value', serverCodeToSort: 'p_value' },
- { name: 'T statistic', serverCodeToSort: 't_statistic' },
+ { name: intl.formatMessage({ id: 'diffExpResultsTable.gene' }), serverCodeToSort: 'gene' },
+ { name: intl.formatMessage({ id: 'diffExpResultsTable.adjustedPValue' }), serverCodeToSort: 'adj_p_val' },
+ { name: intl.formatMessage({ id: 'diffExpResultsTable.averageExpression' }), serverCodeToSort: 'ave_expr' },
+ { name: intl.formatMessage({ id: 'diffExpResultsTable.bStatistic' }), serverCodeToSort: 'b_statistic' },
+ { name: intl.formatMessage({ id: 'diffExpResultsTable.logFoldChange' }), serverCodeToSort: 'log_fc' },
+ { name: intl.formatMessage({ id: 'diffExpResultsTable.pValue' }), serverCodeToSort: 'p_value' },
+ { name: intl.formatMessage({ id: 'diffExpResultsTable.tStatistic' }), serverCodeToSort: 't_statistic' },
]}
defaultSortProp={{ sortField: 'created_at', sortOrderAscendant: false }}
customFilters={customInputs}
showSearchInput
customElements={[
-
+
]}
- searchLabel='Gene'
- searchPlaceholder='Search by Gene'
+ searchLabel={intl.formatMessage({ id: 'diffExpResultsTable.gene' })}
+ searchPlaceholder={intl.formatMessage({ id: 'diffExpResultsTable.searchPlaceholder' })}
urlToRetrieveData={urlDifferentialExpressionExperimentResults + props.differentialExpressionAnalysisId + '/'}
updateWSKey='update_differential_expression_experiments'
mapFunction={(differentialExpressionAnalysis: DiffExpExperimentDetail) => (
diff --git a/src/frontend/static/frontend/src/components/differential-expression/DifferentialExpressionModalResultsVolcanoPlot.tsx b/src/frontend/static/frontend/src/components/differential-expression/DifferentialExpressionModalResultsVolcanoPlot.tsx
index f26e9ec2..43488d5b 100644
--- a/src/frontend/static/frontend/src/components/differential-expression/DifferentialExpressionModalResultsVolcanoPlot.tsx
+++ b/src/frontend/static/frontend/src/components/differential-expression/DifferentialExpressionModalResultsVolcanoPlot.tsx
@@ -3,6 +3,7 @@ import { VolcanoPlot } from './VolcanoPlot'
import ky from 'ky'
import { VolcanoPoint } from './types'
import { Form } from 'semantic-ui-react'
+import { useIntl } from 'react-intl'
declare const urlDifferentialExpressionVolcanoData: string
@@ -17,6 +18,7 @@ interface DifferentialExpressionModalResultsVolcanoPlotProps {
* @returns Component.
*/
export const DifferentialExpressionModalResultsVolcanoPlot = (props: DifferentialExpressionModalResultsVolcanoPlotProps) => {
+ const intl = useIntl()
const [volcanoPoints, setVolcanoPoints] = useState([])
const [fcThreshold, setFcThreshold] = useState(1)
const [pThreshold, setPThreshold] = useState(0.05)
@@ -55,13 +57,15 @@ export const DifferentialExpressionModalResultsVolcanoPlot = (props: Differentia
return (
-
Volcano Plot
+
{intl.formatMessage({ id: 'differentialExpression.volcanoPlot.title' })}
{/* Selects */}
setShowThresholds(Boolean(data.checked))}
diff --git a/src/frontend/static/frontend/src/components/differential-expression/DifferentialExpressionPanel.tsx b/src/frontend/static/frontend/src/components/differential-expression/DifferentialExpressionPanel.tsx
index b0d5025e..5ed691de 100644
--- a/src/frontend/static/frontend/src/components/differential-expression/DifferentialExpressionPanel.tsx
+++ b/src/frontend/static/frontend/src/components/differential-expression/DifferentialExpressionPanel.tsx
@@ -16,6 +16,7 @@ import { StopExperimentButton } from '../pipeline/all-experiments-view/StopExper
import ky from 'ky'
import { EditIcon } from '../common/EditIcon'
import { DifferentialExpressionModalResults } from './DifferentialExpressionModalResults'
+import { useIntl } from 'react-intl'
declare const urlDifferentialExpressionList:string
declare const urlDifferentialExpressionStop:string
@@ -37,6 +38,7 @@ interface DiferentialExpressionPanelState {
* @returns JSX.Element
*/
export const DiferentialExpressionPanel = () => {
+ const intl = useIntl()
const [state, setState] = useState({
alert: getDefaultAlertProps(),
modal: getDefaultConfirmModal(),
@@ -90,10 +92,10 @@ export const DiferentialExpressionPanel = () => {
return { key: id, value: id, text: tag.name }
})
- methodsOptions.unshift({ key: 'no_method', text: 'No method' })
+ methodsOptions.unshift({ key: 'no_method', text: intl.formatMessage({ id: 'differentialExpression.panel.noMethod' }) })
return [
- { label: 'Method', keyForServer: 'tool', defaultValue: '', placeholder: 'Select an existing method', options: methodsOptions, width: 3 }
+ { label: intl.formatMessage({ id: 'differentialExpression.panel.method' }), keyForServer: 'tool', defaultValue: '', placeholder: intl.formatMessage({ id: 'differentialExpression.panel.selectMethod' }), options: methodsOptions, width: 3 }
]
}
@@ -117,12 +119,12 @@ export const DiferentialExpressionPanel = () => {
}).then((response) => {
// If OK closes the modal
if (response.ok) {
- updateAlert(CustomAlertTypes.SUCCESS, 'Differential Expression experiment stopped successfully!')
+ updateAlert(CustomAlertTypes.SUCCESS, intl.formatMessage({ id: 'differentialExpression.panel.stopSuccess' }))
} else {
- updateAlert(CustomAlertTypes.ERROR, 'Error stopping Differential Expression experiment!')
+ updateAlert(CustomAlertTypes.ERROR, intl.formatMessage({ id: 'differentialExpression.panel.stopError' }))
}
}).catch((err) => {
- updateAlert(CustomAlertTypes.ERROR, 'Error stopping Differential Expression experiment!')
+ updateAlert(CustomAlertTypes.ERROR, intl.formatMessage({ id: 'differentialExpression.panel.stopError' }))
console.error('Error stopping FSExperiment ->', err)
}).finally(() => {
setState(prevState => ({ ...prevState, stoppingExperiment: false }))
@@ -140,12 +142,12 @@ export const DiferentialExpressionPanel = () => {
headers: myHeaders,
}).then((response) => {
if (response.ok) {
- updateAlert(CustomAlertTypes.SUCCESS, 'Differential Expression experiment deleted successfully!')
+ updateAlert(CustomAlertTypes.SUCCESS, intl.formatMessage({ id: 'differentialExpression.panel.deleteSuccess' }))
} else {
- updateAlert(CustomAlertTypes.ERROR, 'Error deleting Differential Expression experiment!')
+ updateAlert(CustomAlertTypes.ERROR, intl.formatMessage({ id: 'differentialExpression.panel.deleteError' }))
}
}).catch((err) => {
- updateAlert(CustomAlertTypes.ERROR, 'Error deleting Differential Expression experiment!')
+ updateAlert(CustomAlertTypes.ERROR, intl.formatMessage({ id: 'differentialExpression.panel.deleteError' }))
console.error('Error deleting FSExperiment ->', err)
})
}
@@ -199,16 +201,16 @@ export const DiferentialExpressionPanel = () => {
- headerTitle='Differential Expressions Analyses'
+ headerTitle={intl.formatMessage({ id: 'differentialExpression.panel.headerTitle' })}
headers={[
- { name: 'Name', serverCodeToSort: 'name', width: 2 },
- { name: 'Description', serverCodeToSort: 'description', width: 3 },
- { name: 'Method', serverCodeToSort: 'tool' },
- { name: 'Date', serverCodeToSort: 'created_at' },
- { name: 'State', serverCodeToSort: 'state', width: 1, textAlign: 'center' },
- { name: 'Sources' },
- { name: 'Public', width: 1 },
- { name: 'Actions', width: 2 }
+ { name: intl.formatMessage({ id: 'common.name' }), serverCodeToSort: 'name', width: 2 },
+ { name: intl.formatMessage({ id: 'common.description' }), serverCodeToSort: 'description', width: 3 },
+ { name: intl.formatMessage({ id: 'differentialExpression.panel.method' }), serverCodeToSort: 'tool' },
+ { name: intl.formatMessage({ id: 'common.date' }), serverCodeToSort: 'created_at' },
+ { name: intl.formatMessage({ id: 'common.state' }), serverCodeToSort: 'state', width: 1, textAlign: 'center' },
+ { name: intl.formatMessage({ id: 'differentialExpression.panel.sources' }) },
+ { name: intl.formatMessage({ id: 'differentialExpression.panel.public' }), width: 1 },
+ { name: intl.formatMessage({ id: 'common.actions' }), width: 2 }
]}
defaultSortProp={{ sortField: 'created_at', sortOrderAscendant: false }}
customFilters={getDefaultFilters()}
@@ -224,7 +226,9 @@ export const DiferentialExpressionPanel = () => {
*/
]}
- searchLabel='Name/Description'
+ searchLabel={intl.formatMessage({
+ id: 'differentialExpression.panel.nameDescription'
+ })}
searchPlaceholder='Search by name/description'
urlToRetrieveData={urlDifferentialExpressionList}
updateWSKey='update_differential_expression_experiments'
@@ -255,14 +259,18 @@ export const DiferentialExpressionPanel = () => {
source={differentialExpressionAnalysis.mrna_source}
iconName='file'
iconColor={GenesColors.MRNA}
- downloadButtonTitle='Download source mRNA file'
+ downloadButtonTitle={intl.formatMessage({
+ id: 'differentialExpression.panel.downloadMrnaSource'
+ })}
/>
>
@@ -272,14 +280,18 @@ export const DiferentialExpressionPanel = () => {
differentialExpressionAnalysis.is_public
? (
)
: (
@@ -295,7 +307,9 @@ export const DiferentialExpressionPanel = () => {
onClick={() => { openInferenceResult(differentialExpressionAnalysis) }}
className='clickable'
color='blue'
- title='See results'
+ title={intl.formatMessage({
+ id: 'differentialExpression.panel.seeResults'
+ })}
/>
)
}
@@ -313,8 +327,10 @@ export const DiferentialExpressionPanel = () => {
{
isInProcess && (
handleChangeConfirmModalState(true, 'Stop Experiment', 'Are you sure to stop experiment?', () => confirmExperimentStop(differentialExpressionAnalysis.id))}
+ title={intl.formatMessage({
+ id: 'differentialExpression.panel.stopExperiment'
+ })}
+ onClick={() => handleChangeConfirmModalState(true, intl.formatMessage({ id: 'differentialExpression.panel.stopExperimentTitle' }), intl.formatMessage({ id: 'differentialExpression.panel.stopExperimentConfirm' }), () => confirmExperimentStop(differentialExpressionAnalysis.id))}
ownerId={differentialExpressionAnalysis.user.id as number}
/>
)
@@ -323,7 +339,9 @@ export const DiferentialExpressionPanel = () => {
{/* Delete button */}
{(!isInProcess && !differentialExpressionAnalysis.is_public) && (
confirmExperimentDeletion(differentialExpressionAnalysis)}
ownerId={differentialExpressionAnalysis.user.id}
/>
diff --git a/src/frontend/static/frontend/src/components/differential-expression/VolcanoPlot.tsx b/src/frontend/static/frontend/src/components/differential-expression/VolcanoPlot.tsx
index 5be970cd..e5b3b516 100644
--- a/src/frontend/static/frontend/src/components/differential-expression/VolcanoPlot.tsx
+++ b/src/frontend/static/frontend/src/components/differential-expression/VolcanoPlot.tsx
@@ -1,5 +1,6 @@
import React from 'react'
import Plot from 'react-plotly.js'
+import { useIntl } from 'react-intl'
type VolcanoPoint = {
id: string | number
@@ -26,6 +27,7 @@ export const VolcanoPlot = ({
pThreshold = 0.05,
showThresholds
}: VolcanoPlotProps) => {
+ const intl = useIntl()
const transformP = (p: number) => -Math.log10(p)
const significant = data.filter(
diff --git a/src/frontend/static/frontend/src/components/faq/FAQ.tsx b/src/frontend/static/frontend/src/components/faq/FAQ.tsx
new file mode 100644
index 00000000..3ad9e357
--- /dev/null
+++ b/src/frontend/static/frontend/src/components/faq/FAQ.tsx
@@ -0,0 +1,216 @@
+import React from 'react'
+import { Container, Divider, Grid, Header, List } from 'semantic-ui-react'
+import { Base } from '../Base'
+import { FAQQuestionAndAnswer } from './FAQQuestionAndAnswer'
+import { useIntl } from 'react-intl'
+/**
+ * FAQ Page (Frequently Asked Questions).
+ *
+ * Uses the `FAQQuestionAndAnswer` component to display each questions and answers.
+ */
+
+export const FAQ = () => {
+ const intl = useIntl()
+
+ return (
+
+
+
+
+
+ {intl.formatMessage({ id: 'faq.pageTitle' })}
+
+
+ {/* Question 1: What is Multiomix? */}
+
+ {intl.formatMessage({ id: 'faq.whatIs.answer' })} (
+ {intl.formatMessage({ id: 'faq.whatIs.link' })} )
+
+ )}
+ />
+
+ {/* Question 2: What kind of analysis can I do? */}
+
+ {intl.formatMessage({ id: 'faq.analysisTypes.answer' })}
+
+ )}
+ />
+
+ {/* Question 3: Pipelines and statistical methods */}
+
+
+ {intl.formatMessage({ id: 'faq.pipelines.p1' })}
+
+
+ {intl.formatMessage({ id: 'faq.pipelines.p2' })}
+
+
+ {intl.formatMessage({ id: 'faq.pipelines.p3' })}
+
+ >
+ )}
+ />
+
+ {/* Question 4: Uploading own data */}
+
+ {intl.formatMessage({ id: 'faq.uploadData.answer' })}
+
+ )}
+ />
+ {/* Question 5: Public datasets */}
+
+ {intl.formatMessage({ id: 'faq.datasetsPublic.answer' })}
+
+ )}
+ />
+
+ {/* Question 6: cBioPortal datasets preprocessing */}
+
+
+ {intl.formatMessage({ id: 'faq.datasetsPreprocessing.p1' })}
+
+
+ {intl.formatMessage({ id: 'faq.datasetsPreprocessing.p2' })}
+
+ >
+ )}
+ />
+ {/* Question 7: Only for experts? */}
+
+ {intl.formatMessage({ id: 'faq.expertise.answer' })}
+
+ )}
+ />
+
+ {/* Question 8: Performance for correlation analysis */}
+
+ {intl.formatMessage({ id: 'faq.performance.answer' })}{' '}
+ GGCA
+
+ )}
+ />
+
+ {/* Question 9: Metaheuristics acceleration */}
+
+ {intl.formatMessage({ id: 'faq.metaheuristics.answer' })} (
+ {intl.formatMessage({ id: 'faq.metaheuristics.link' })} )
+
+ )}
+ />
+ {/* Question 10: Ecosystem integrations */}
+
+ {intl.formatMessage({ id: 'faq.integrations.answer' })}{' '}
+ BioAPI {' '}
+ Modulector
+
+ )}
+ />
+ {/* Question 11: Internal technologies */}
+
+ {intl.formatMessage({ id: 'faq.technologies.answer' })} (
+ GitHub )
+
+ )}
+ />
+
+
+ {/* Question 12: Privacy */}
+
+ {intl.formatMessage({ id: 'faq.privacy.answer' })}
+
+ )}
+ />
+ {/* Question 13: Local installation */}
+
+ {intl.formatMessage({ id: 'faq.installation.answer' })} (
+ GitHub )
+
+ )}
+ />
+
+
+ {/* Question 14: Licenses */}
+
+ {intl.formatMessage({ id: 'faq.licenses.answer' })}
+
+ )}
+ />
+ {/* Question 15: Additional Links */}
+
+ {intl.formatMessage({ id: 'faq.footer.links.siteMap' })}
+ {intl.formatMessage({ id: 'faq.footer.links.contact' })}
+ {intl.formatMessage({ id: 'faq.footer.links.terms' })}
+ {intl.formatMessage({ id: 'faq.footer.links.privacy' })}
+
+ )}
+ />
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/src/frontend/static/frontend/src/components/files-manager/FilesManager.tsx b/src/frontend/static/frontend/src/components/files-manager/FilesManager.tsx
index 38c2058b..a7fe5664 100644
--- a/src/frontend/static/frontend/src/components/files-manager/FilesManager.tsx
+++ b/src/frontend/static/frontend/src/components/files-manager/FilesManager.tsx
@@ -14,6 +14,7 @@ import { TagLabel } from '../common/TagLabel'
import { PopupIcons } from '../common/PopupIcons'
import { SwitchPublicButton } from '../common/SwitchPublicButton'
import { DeleteButton } from '../common/DeleteButton'
+import { useIntl } from 'react-intl'
/** Structure returned from the chunk upload service. */
type UploadResponse = {
@@ -114,6 +115,7 @@ class FilesManager extends React.Component
* @returns An object with all the field with default values
*/
getDefaultNewFile (): NewFile {
+ const { intl } = this.props
return {
newFileName: FILE_INPUT_LABEL,
newFileNameUser: '',
diff --git a/src/frontend/static/frontend/src/locales/en.ts b/src/frontend/static/frontend/src/locales/en.ts
new file mode 100644
index 00000000..b868a26e
--- /dev/null
+++ b/src/frontend/static/frontend/src/locales/en.ts
@@ -0,0 +1,734 @@
+export default {
+ // common actions
+ 'common.cancel': 'Cancel',
+ 'common.delete': 'Delete',
+ 'common.stop': 'Stop',
+ 'common.save': 'Save',
+ 'common.close': 'Close',
+ 'common.actions': 'Actions',
+ 'common.confirm': 'Confirm',
+ 'common.sample': 'Sample',
+ 'common.goBack': 'Go back',
+ 'common.search': 'Search',
+ 'common.details': 'Details',
+ 'common.noDetails': 'No details found',
+ 'common.name': 'Name',
+ 'common.description': 'Description',
+ 'common.requiredField': 'Required field',
+ 'common.model': 'Model:',
+ 'common.date': 'Date',
+ 'common.datasets': 'Datasets',
+ // common Labels
+ 'common.algorithm': 'Algorithm',
+ 'common.nClusters': 'Number of clusters',
+ 'common.metric': 'Metric',
+ 'common.scoringMethod': 'Scoring method',
+ 'common.randomState': 'Random state',
+ 'common.penalizer': 'Penalizer',
+ 'common.integerPlaceholder': 'An integer number',
+ 'common.numberOfIterations': 'Number of iterations',
+ 'common.coefficient': 'Coefficient',
+ 'common.table': 'Table',
+ // common Forms and steps
+ 'common.basicData': 'Basic data',
+ 'common.descriptionOptional': 'Description (optional)',
+ 'common.continue': 'Continue',
+ 'common.numberOfFolds': 'Number of folds',
+ // common Tables and states
+ 'common.state': 'State',
+ 'common.cluster': 'Cluster',
+ 'common.relations': 'Relations',
+
+ // Auth/user
+ 'auth.login': 'Log in',
+ 'auth.greeting': 'Hi, {username}',
+ 'auth.editProfile': 'Edit profile',
+ 'auth.logout': 'Exit',
+
+ // Menús
+ 'menu.analysis': 'Analysis',
+ 'menu.gem': 'GEM',
+ 'menu.gem.tooltip': 'Gene Expression Modulation',
+ 'menu.biomarkers': 'Biomarkers',
+ 'menu.datasets': 'Datasets',
+ 'menu.multiomix': 'Multiomix',
+ 'menu.cbioportal': 'cBioPortal',
+ 'menu.institutions': 'Institutions',
+ 'menu.admin': 'Admin',
+ 'menu.admin.genes': 'Database: Genes',
+ 'menu.about': 'About us',
+ 'menu.faq': 'Frequently Asked Questions',
+ 'menu.opensource': 'Open Source',
+
+ // About us
+ 'about.description': 'Multiomix is the result of interdisciplinary work between members of the following scientific institutions:',
+ 'about.institution.caeti': 'CAETI - Universidad Abierta Interamericana',
+ 'about.institution.ciniba': 'CINIBA - Faculty of Medical Sciences - UNLP',
+ 'about.institution.lidi': 'LIDI - Faculty of Informatics - UNLP',
+
+ 'about.coordination': 'Project coordination:',
+
+ 'about.members.title': 'Project members:',
+ 'about.members.main': 'Main contributor:',
+ 'about.members.collaborators': 'Collaborators:',
+
+ 'about.contact.title': 'Contact:',
+ 'about.contact.questions': 'For questions or suggestions please contact us:',
+ 'about.contact.institutions': 'You can also contact us for creating your research institution. It will let researchers share datasets inside Multiomix.',
+
+ // BIOMARKERS
+ // 1.BiomarkerInferenceExperimentsPanel.tsx
+ 'inference.experiment.title': 'Inference experiment "{name}"',
+ // 2.InferenceExperimentClinicalAttributeSelect.tsx label
+ 'inference.clinicalAttribute.label': 'Group by clinical attribute',
+ 'inference.clinicalAttribute.placeholder': 'Clinical attribute to group by',
+ // 3.InferenceExperimentResultMetrics.tsx
+ 'inference.metrics.title': '"{name}" metrics',
+ 'inference.model': 'Model',
+ // 5.InferenceExperimentsTable.tsx
+ 'inference.stop.title': 'Stop inference experiment',
+ 'inference.stop.confirm': 'Are you sure you want to stop the inference experiment "{name}"?',
+ 'inference.stop.cancel': '{common.cancel}',
+ 'inference.stop.button': '{common.stop}',
+
+ 'inference.delete.title': 'Delete experiment',
+ 'inference.delete.confirm': 'Are you sure you want to delete the inference experiment "{name}"?',
+ 'inference.delete.cancel': '{common.cancel}',
+ 'inference.delete.button': '{common.delete}',
+
+ 'inference.table.title': 'Inference experiments',
+ 'inference.table.columns.model': 'Model',
+ 'inference.table.columns.dataset': 'Datasets',
+
+ 'inference.search.placeholder': 'Search by name or description',
+
+ 'inference.new.title': 'New inference experiment',
+ 'inference.results.title': 'See results',
+ 'inference.results.tooltip': 'View experiment results',
+ // 6.NewInferenceExperimentModal.tsx
+ 'inference.newInference.title': 'Create new inference experiment',
+ 'inference.new.step1': 'Step 1: Trained model',
+ 'inference.new.step2': 'Step 2: molecules datasets',
+ // 7.SamplesAndGroupsInferenceTable.tsx
+ 'inference.table.download.tooltip': 'Download results in a CSV file',
+ 'inference.table.filter.cluster.placeholder': 'Filter by cluster',
+ 'inference.table.addClusterLabels': 'Add Cluster labels',
+ // 8.SamplesAndTimeInferenceCharts.tsx
+ 'inference.charts.noAttribute': 'No clinical attribute selected',
+ 'inference.charts.selectAttribute': 'Please, select one in the right Select.',
+ // 9.SamplesAndTimeInferenceTable.tsx
+ 'inference.timeTable.columns.predictedTime': 'Predicted time',
+ 'inference.timeTable.filter.range.label': 'Range',
+ 'inference.timeTable.filter.range.placeholder': 'Filter by range',
+ 'inference.timeTable.menu.table': 'Table',
+ 'inference.timeTable.menu.charts': 'Charts',
+ 'inference.timeTable.menu.table.info': 'Table with all the samples and their predicted hazard/survival time',
+ 'inference.timeTable.menu.charts.info': 'Shows some charts with the samples and their predicted hazard/survival time grouped by some condition',
+ 'inference.timeTable.addRangeLabels': 'Add Range labels',
+ // 10.molecules/GeneOntologyCytoscapeChart.tsx
+ 'geneOntology.form.ontologyType': 'Ontology type',
+ 'geneOntology.form.generalDepth': 'General depth',
+ 'geneOntology.form.hierarchicalDepth': 'Hierarchical depth to children',
+ 'geneOntology.form.toRoot': 'To root',
+ 'geneOntology.relation.hasPart': 'Has part',
+ 'geneOntology.relation.isA': 'Is a',
+ 'geneOntology.relation.partOf': 'Part of',
+ 'geneOntology.relation.regulates': 'Regulates',
+ // 11.GeneOntologyPanel
+ 'geneOntology.panel.filterType': 'Filter type',
+ 'geneOntology.panel.filterType.intersection': 'Intersection',
+ 'geneOntology.panel.filterType.union': 'Union',
+ 'geneOntology.panel.filterType.enrichment': 'Enrichment',
+ 'geneOntology.panel.pValueThreshold': 'P-value threshold',
+ 'geneOntology.panel.correctionMethod': 'Correction method',
+ 'geneOntology.panel.correctionMethod.analytical': 'Analytical',
+ 'geneOntology.panel.correctionMethod.bonferroni': 'Bonferroni',
+ 'geneOntology.panel.correctionMethod.falseDiscoveryRate': 'False discovery rate',
+ 'geneOntology.panel.relationType': 'Relation type',
+ 'geneOntology.panel.relationType.enables': 'Enables',
+ 'geneOntology.panel.relationType.involvedIn': 'Involved in',
+ 'geneOntology.panel.relationType.partOf': 'Part of',
+ 'geneOntology.panel.relationType.locatedIn': 'Located in',
+ 'geneOntology.panel.ontologyType': 'Ontology type',
+ 'geneOntology.panel.ontologyType.biologicalProcess': 'Biological process',
+ 'geneOntology.panel.ontologyType.molecularFunction': 'Molecular function',
+ 'geneOntology.panel.ontologyType.cellularComponent': 'Cellular component',
+ 'geneOntology.panel.table.term': 'Term',
+ 'geneOntology.panel.table.ontologyType': 'Ontology type',
+ // 12.GENES.ActionableCancerGenesPanel.tsx
+ 'actionableCancerGenes.panel.title': 'Actionable Cancer Genes Panel',
+ // 13.GeneAssociationsNetworkPanel
+ 'geneAssociations.relation.fusion': 'Fusion',
+ 'geneAssociations.relation.coOccurrence': 'Co-occurrence',
+ 'geneAssociations.relation.experimental': 'Experimental',
+ 'geneAssociations.relation.textMining': 'Text mining',
+ 'geneAssociations.relation.database': 'Database',
+ 'geneAssociations.relation.coExpression': 'Co-expression',
+ 'geneAssociations.form.minCombinedScore': 'Min combined score',
+ 'geneAssociations.infoPopup.text': 'The combined score is computed by combining the probabilities from the different evidence channels and corrected for the probability of randomly observing an interaction. For a more detailed description please see von Mering, et al. Nucleic Acids Res. 2005',
+ // 14.GeneInformation.tsx
+ 'geneInformation.context.gene': 'for this gene',
+ 'geneInformation.summary': 'Summary',
+ // 15.MetabolicPathwaysPanel.tsx
+ 'metabolicPathways.infoPopup': 'List of genes that are involved in a pathway for a given database',
+ 'metabolicPathways.header': 'Metabolic pathways',
+ 'metabolicPathways.selectSource': 'Select a source',
+ 'metabolicPathways.sourcePlaceholder': 'Source',
+ // 16.PathwaysInformation.tsx
+ 'pathwaysInformation.context.gene': 'for this gene',
+ 'pathwaysInformation.context.pathways': 'for this gene',
+ // 17.MethylationInformation.tsx
+ 'methylationInformation.context.site': 'for this methylation site',
+ 'methylationInformation.infoPopup.aliases': 'Methylation aliases and chromosome position',
+ 'methylationInformation.header': 'Methylation Information',
+ 'methylationInformation.chromosomePosition': 'Chr. Position:',
+ 'methylationInformation.infoPopup.ucsc': 'List of islands related to the methylation site according to the UCSC database',
+ 'methylationInformation.header.ucsc': 'UCSC CpG Islands',
+ 'methylationInformation.table.cpgIsland': 'CpG Island',
+ 'methylationInformation.table.relation': 'Relation',
+ 'methylationInformation.infoPopup.genes': 'Genes related to this methylation site and the regions where the methylation site is located. These regions, according to the NCBI RefSeq database, can be: 5UTR=5\' untranslated region between the Transcription Start Site (TTS) and ATG start site, 3UTR=3\' untranslated region between the stop codon and poly A signal, exon_#, TSS200=1-200 bp 5\' the TSS, or TS1500=200-1500 bp 5\' of the TSS',
+ 'methylationInformation.header.genes': 'Related genes',
+ 'methylationInformation.table.gene': 'Gene',
+ 'methylationInformation.table.regions': 'Regions',
+ // 18.CurrentMoleculeDetails.tsx
+ 'currentMoleculeDetails.noSelection': 'No molecule selected',
+ 'currentMoleculeDetails.selectOne': 'Select one in the left panel',
+ // 19.MoleculesDetailsMenu.tsx
+ 'moleculesDetailsMenu.details.info': 'Details of {identifier} obtained from different standardized sources',
+ 'moleculesDetailsMenu.geneAssociations': 'Gene associations network',
+ 'moleculesDetailsMenu.geneAssociations.info': 'It shows the network of gene associations of the genes of this biomarker',
+ 'moleculesDetailsMenu.geneOntology': 'Gene Ontology',
+ 'moleculesDetailsMenu.geneOntology.info': 'Gene Ontology (GO) is a powerful tool for understanding the biological processes, molecular functions, and cellular components associated with a gene',
+ 'moleculesDetailsMenu.diseases': 'Diseases',
+ 'moleculesDetailsMenu.diseases.info': 'Interactions of the molecule with diseases that have been reported in the literature',
+ 'moleculesDetailsMenu.drugs': 'Drugs',
+ 'moleculesDetailsMenu.drugs.info': 'Interactions of the molecule with drugs that have been reported in the literature',
+ 'moleculesDetailsMenu.miRNAGeneInteractions': 'miRNA-Gene interactions',
+ 'moleculesDetailsMenu.miRNAGeneInteractions.info': 'Different miRNA-Gene interactions that have been reported in the literature along with the associated mirDIP score and Pubmed sources',
+ // 20.MoleculesTable.tsx
+ 'moleculesTable.type.mrna': 'mRNA',
+ 'moleculesTable.type.mirna': 'miRNA',
+ 'moleculesTable.type.cna': 'CNA',
+ 'moleculesTable.type.methylation': 'Methylation',
+ 'moleculesTable.header.identifier': 'Identifier',
+ 'moleculesTable.header.type': 'Type',
+ 'moleculesTable.header.actions': 'Actions',
+ // 21.SamplesAndGroupsTable.tsx
+ 'samplesAndGroupsTable.filter.cluster.placeholder': 'Filter by cluster',
+ // 22.StatisticalValidationResultBestFeatures.tsx
+ 'statValidationBestFeatures.axis.molecule': 'Molecule',
+ 'statValidationBestFeatures.context.features': 'significant features found for this statistical validation',
+ // 23.StatisticalValidationResultKaplanMeier.tsx
+ 'kaplanMeier.axis.time': 'Time',
+ 'kaplanMeier.axis.probability': 'Probability',
+ 'kaplanMeier.info.coxRegression': 'These metrics are computed using Cox-Regression',
+ 'kaplanMeier.header.clusteringMetrics': 'Clustering metrics',
+ 'kaplanMeier.button.clusteringModel': 'Clustering model',
+ 'kaplanMeier.button.groupByClinical': 'Group by clinical',
+ 'kaplanMeier.select.clinicalAttribute': 'Clinical attribute to group by',
+ 'kaplanMeier.metric.cIndex': 'C-Index',
+ 'kaplanMeier.metric.partialLogLikelihood': 'Partial Log-Likelihood',
+ 'kaplanMeier.button.seeSamplesAndClusters': 'See samples and clusters',
+ 'kaplanMeier.modal.samplesAndClusters': 'Samples and clusters',
+ // 24.StatisticalValidationResultMetrics.tsx
+ 'statValidationMetrics.header.metrics': 'metrics',
+ 'statValidationMetrics.header.validationMetrics': 'Validation metrics',
+ 'statValidationMetrics.metric.mse': 'MSE',
+ 'statValidationMetrics.metric.r2Score': 'R2 score',
+ // 25.NewStatisticalValidationModal.tsx
+ 'newStatValidation.header.create': 'Create new statistical validation',
+ 'newStatValidation.step.trainedModel': 'Step 1: Trained model',
+ 'newStatValidation.step.validationDatasets': 'Step 2: Validation datasets',
+ // 26.StatisticalValidationMenu.tsx
+ 'statValidationMenu.bestFeatures': 'Most significant features',
+ 'statValidationMenu.bestFeatures.info': 'Most significant features for the survival analysis',
+ 'statValidationMenu.kaplanMeier': 'Kaplan-Meier',
+ 'statValidationMenu.kaplanMeier.info': 'curve showing survival or hazard ratio',
+ 'statValidationMenu.heatmap': 'Heatmap',
+ 'statValidationMenu.heatmap.info': 'Heatmap for every sample and molecule',
+ // 27.StatisticalValidationsTable.tsx
+
+ 'statValidationsTable.stopValidation.header': 'Stop statistical validation',
+ 'statValidationsTable.stopValidation.confirm': 'Are you sure you want to stop the statistical validation {name}?',
+ 'statValidationsTable.deleteValidation.header': 'Delete statistical validation',
+ 'statValidationsTable.deleteValidation.confirm': 'Are you sure you want to delete the statistical validation {name}?',
+ 'statValidationsTable.headerTitle': 'Statistical validations',
+ 'statValidationsTable.headers.model': 'Model',
+ 'statValidationsTable.headers.datasets': 'Datasets',
+ 'statValidationsTable.headers.actions': 'Actions',
+ 'statValidationsTable.newValidation': 'New statistical validation',
+ 'statValidationsTable.actions.seeResults': 'See results',
+ 'statValidationsTable.actions.stopValidation': 'Stop statistical validation',
+ 'statValidationsTable.actions.deleteValidation': 'Delete statistical validation',
+ // 28.NewClusteringModelForm.tsx
+ 'newClusteringForm.placeholder.algorithm': 'Select an algorithm',
+ 'newClusteringForm.label.searchOptimalClusters': 'Search for the optimal number of clusters',
+ 'newClusteringForm.info.nClusters': 'The number of clusters to group the data into. The optimal number can be found by looking for the elbow in the curve of the sum of squared distances between samples and their closest cluster center.',
+ 'newClusteringForm.placeholder.metric': 'Select a metric',
+ 'newClusteringForm.placeholder.scoringMethod': 'Select a method',
+ 'newClusteringForm.info.algorithm': 'K-Means: Groups data by minimizing intra-cluster variance; effective for RNA and miRNA. Spectral Clustering: Uses graph-based similarity to identify complex patterns; ideal for methylation and CNA. BK-Means: A hierarchical variation of K-Means, suitable for layered clustering of clinical and multi-omics datasets. Ward’s Method: Minimizes variance in hierarchical clustering; well-suited for combining RNA and methylation data.',
+ 'newClusteringForm.info.metric': 'Cox Regression: A proportional hazards model to identify associations between multi-omics features and clinical outcomes. Log-Rank Test: A non-parametric test to compare survival distributions; currently not available.',
+ 'newClusteringForm.info.scoringMethod': 'C-Index: A measure of concordance between predicted and observed survival outcomes; higher values indicate better performance. Log Likelihood: The probability of observing the data given the model; lower values indicate better performance.',
+ 'newClusteringForm.info.randomState': 'The seed used by the random number generator to ensure reproducibility.',
+ 'newClusteringForm.info.penalizer': 'Useful when clinical data has few samples or events; increases robustness and avoids NaN values.',
+ // 29.NewRFModelForm.tsx
+ 'newRFForm.label.searchOptimalTrees': 'Search for the optimal number of trees',
+ 'newRFForm.info.searchOptimalTrees': 'This option is useful when the number of samples in the clinical data is small or there are few observed events; setting this value increases the robustness of the model in such cases, avoiding problems with NaN values.',
+ 'newRFForm.label.maxDepth': 'Max depth',
+ 'newRFForm.info.maxDepth': 'The maximum depth of the tree',
+ 'newRFForm.info.randomState': 'Seed used by the random number generator',
+ 'newRFForm.label.nEstimators': 'Number of trees',
+ 'newRFForm.info.nEstimators': 'The number of trees (estimators) used in the Random Forest model.',
+ // 30.NewSVMModelForm.tsx
+ 'newSVMForm.info.kernel.linear': 'Linear Kernel: Best for linearly separable data; commonly used for simple genomic or clinical feature classification.',
+ 'newSVMForm.info.kernel.polynomial': 'Polynomial Kernel: Captures non-linear patterns; effective for complex relationships in multi-omics data.',
+ 'newSVMForm.info.kernel.rbf': 'RBF Kernel: Maps data to a higher-dimensional space; ideal for handling non-linear separations in RNA and methylation analyses.',
+ 'newSVMForm.placeholder.kernel': 'Select a kernel',
+ 'newSVMForm.label.maxIterations': 'Max iterations',
+ 'newSVMForm.info.maxIterations': 'The maximum number of iterations to be run',
+ 'newSVMForm.info.randomState': 'Seed used by the random number generator',
+ // 31.NewTrainedModelModal
+ 'newTrainedModelModal.header.create': 'Create new trained model',
+
+ 'newTrainedModelModal.step1.trainingParameters': 'Step 1: Training parameters',
+ 'newTrainedModelModal.step2.trainingDatasets': 'Step 2: Training datasets',
+
+ 'newTrainedModelModal.header.selectModel': 'Select a new model to train',
+ 'newTrainedModelModal.placeholder.selectModel': 'Select a model',
+ 'newTrainedModelModal.header.selectModelParameters': 'Select model parameters',
+ 'newTrainedModelModal.header.selectCVParameters': 'Select Cross Validation parameters',
+ 'newTrainedModelModal.info.numberOfFolds': 'Defines the number of data splits for cross-validation; ensures robust model evaluation and prevents overfitting.',
+ // 32.BiomarkerTrainedModelsTable
+ 'biomarkerTrainedModelsTable.header.stopTraining': 'Stop training',
+ 'biomarkerTrainedModelsTable.confirm.stopTraining': 'Are you sure you want to stop the training of model {modelName}?',
+ 'biomarkerTrainedModelsTable.button.stop': 'Stop',
+ 'biomarkerTrainedModelsTable.header.deleteBiomarker': 'Delete Biomarker',
+ 'biomarkerTrainedModelsTable.confirm.deleteBiomarker': 'Are you sure you want to delete the Biomarker {modelName}?',
+ 'biomarkerTrainedModelsTable.header.trainedModels': 'Trained models',
+ 'biomarkerTrainedModelsTable.header.model': 'Model',
+ 'biomarkerTrainedModelsTable.header.bestCVMetric': 'Best CV metric',
+ 'biomarkerTrainedModelsTable.header.datasets': 'Datasets',
+ 'biomarkerTrainedModelsTable.header.actions': 'Actions',
+ 'biomarkerTrainedModelsTable.filter.modelType': 'Model type',
+ 'biomarkerTrainedModelsTable.button.newTrainedModel': 'New trained model',
+ 'biomarkerTrainedModelsTable.search.placeholder': 'Search by name or description',
+ 'biomarkerTrainedModelsTable.button.stopTrainedModel': 'Stop trained model',
+ 'biomarkerTrainedModelsTable.button.deleteTrainedModel': 'Delete trained model',
+ 'biomarkerTrainedModelsTable.button.deleteTrainedModelNotAllowed': 'Trained model cannot be deleted as it has related statistical validations and/or inference experiments',
+ // 33.ModelDetailsPanels
+ 'modelDetails.general.bestFitnessValue': 'Best fitness value:',
+ 'modelDetails.svm.task': 'Task:',
+ 'modelDetails.rf.numberOfEstimators': 'Number of estimators:',
+ 'modelDetails.rf.maxDepth': 'Max. depth:',
+ // 34.BiomarkerStateLabel
+ 'biomarkerState.completed': 'The experiment is complete',
+ 'biomarkerState.finishedWithError': 'The experiment has finished with errors. Try again',
+ 'biomarkerState.waitingForQueue': 'The process of this experiment will start soon',
+ 'biomarkerState.noSamplesInCommon': "Datasets don't have samples in common",
+ 'biomarkerState.inProcess': 'The experiment is being processed',
+ 'biomarkerState.stopping': 'The experiment is being stopped',
+ 'biomarkerState.stopped': 'The experiment was stopped',
+ 'biomarkerState.reachedAttemptsLimit': 'The experiment has failed several times. Try changing some parameters and try again',
+ 'biomarkerState.noFeaturesFound': 'No features were found. Try changing some parameters and try again',
+ 'biomarkerState.emptyDataset': 'After filtering out invalid values such as NaN or inf, there were no molecules or samples to make inference. Perhaps the requested molecules do not exist in the dataset, or all patients contain NaN or inf data. Try changing the dataset used or correct your data and try again.',
+ 'biomarkerState.noValidMolecules': 'The dataset used has not enough molecules to compute the experiment (i.e.: has different molecules than the specified in the Biomarker). Select other dataset and try again',
+ 'biomarkerState.numberOfSamplesFewerThanCvFolds': 'There is a less number of members of each class than the number of CrossValidation folds. We tried to set a lower split number but it still failed. Try selecting a larger dataset and try again',
+ 'biomarkerState.timeoutExceeded': 'The analysis has reached the timeout limit. Try changing some parameters and try again',
+ // 35.SVMKernelTask
+ 'svmTask.regression': 'Regression',
+ 'svmTask.ranking': 'Ranking',
+ // 36.TrainedModelStateLabel
+ 'trainedModelState.completed': 'The experiment is complete{cvModified, select, true { (number of CrossValidation folds were modified to be stratified)} false {}}',
+ 'trainedModelState.finishedWithError': 'The experiment has finished with errors. Try again',
+ 'trainedModelState.waitingForQueue': 'The process of this experiment will start soon',
+ 'trainedModelState.noSamplesInCommon': "Datasets don't have samples in common",
+ 'trainedModelState.inProcess': 'The experiment is being processed',
+ 'trainedModelState.stopping': 'The experiment is being stopped',
+ 'trainedModelState.stopped': 'The experiment was stopped',
+ 'trainedModelState.reachedAttemptsLimit': 'The experiment has failed several times. Try changing some parameters and try again',
+ 'trainedModelState.noFeaturesFound': 'No features were found. Try changing some parameters and try again',
+ 'trainedModelState.noBestModelFound': 'No model could be obtained. Maybe there are fewer samples than number of folds in the CrossValidation or the data presents high collinearity. Try changing some parameters as penalizer or number of folds in the CV process and try again',
+ 'trainedModelState.numberOfSamplesFewerThanCvFolds': 'There is a less number of members of each class than the number of CrossValidation folds. We tried to set a lower split number but it still failed. Try selecting a larger dataset and try again',
+ 'trainedModelState.modelDumpNotAvailable': 'The Feature Selection process has finished correctly, but there was a problem obtaining the model. Try training a new model',
+ 'trainedModelState.timeoutExceeded': 'The training process has reached the timeout limit. Try changing some parameters and try again',
+ 'trainedModelState.emptyDataset': 'After filtering out invalid values such as NaN or inf, there were no molecules or samples to train the model. Perhaps the requested molecules do not exist in the dataset, or all patients contain NaN or inf data. Try changing the dataset used or correct your data and try again.',
+ // 37.BiomarkerTypeSelection
+ 'biomarkerType.createNew': 'Create a new Biomarker',
+ 'biomarkerType.chooseType': 'Choose type of Biomarker',
+ 'biomarkerType.empty.title': 'Empty',
+ 'biomarkerType.empty.description': 'Create an empty Biomarker. You can later add molecules or features (genes, microRNAs, DNA methylation, CNAs) that will make up the biomarker',
+ 'biomarkerType.featureSelection.title': 'Feature Selection/ML',
+ 'biomarkerType.featureSelection.description': 'As a starting point, you can select a previously discovered Biomarker, a well-known Biomarker, or a superset of genes that you would like to test. This method will select the molecular subset that fits the better prediction',
+ // 38.BBHAAdvanced
+ 'bbha.numberOfStars': 'Number of stars',
+ 'bbha.numberOfStars.info': 'Number of stars in the Binary Black Hole Algorithm. Each of these stars evaluates a different subset of features. Increasing this number increases the chances of evaluating the most optimal subset but delays more the result of the experiment',
+ 'bbha.numberOfIterations.info': 'Number of iterations in the Binary Black Hole Algorithm. In each of the iterations, the fitness function for each of the stars with its corresponding subset of features is computed. Increasing this number allows to evaluate more combinations of features but delays more the result of the experiment',
+ 'bbha.version': 'BBHA Version',
+ 'bbha.version.original': 'The Original approach executes the original Binary Black Hole Algorithm as defined in',
+ 'bbha.version.v2': 'Version 2 is an improved version defined in this',
+ 'bbha.coefficientExplanation': 'Coefficient specified in the',
+ 'bbha.useSpark': 'Try to optimize using Apache Spark',
+ 'bbha.useSpark.info': 'If this option is enabled, the experiment will be executed (if possible) using Apache Spark to optimize execution times',
+ // 39.CoxRegressionAdvanced
+ 'coxRegression.keepTopN': 'Keep top N',
+ 'coxRegression.keepTopN.info': 'Maximum number of features to be retained after processing. The features are ordered in descending order by their coefficients, keeping the most significant ones first. If this value is left empty, all those whose coefficients are different from 0 will be retained',
+ // 40.GAAdvanced
+ 'ga.populationSize': 'Population size',
+ 'ga.populationSize.info': 'Number of candidate solutions (individuals or potential solutions) that coexist in each generation of the genetic algorithm. Increasing this number allows to evaluate more combinations of features but delays more the result of the experiment',
+ 'ga.mutationRate': 'Mutation rate',
+ 'ga.floatPlaceholder': 'A float number',
+ 'ga.mutationRate.info': 'Determines the probability that a bit (binary digit) in a candidate solution will be altered or flipped randomly during the evolution process. This option introduces small random changes to explore new possibilities.',
+ 'ga.numberOfIterations.info': 'Number of iterations in the Genetic Algorithms. In each of the iterations, the fitness function for each candidate solution with its corresponding subset of features is computed. Increasing this number allows to evaluate more combinations of features but delays more the result of the experiment',
+ 'ga.useSpark': 'Try to optimize using Apache Spark',
+ 'ga.useSpark.info': 'If this option is enabled, the experiment will be executed (if possible) using',
+ // 41.ClusteringPanel
+ 'clustering.algorithm.placeholder': 'Clustering Algorithm',
+ // 42.RFPanel
+ 'rf.numberOfEstimators': 'Number of estimators',
+ 'rf.maxDepth': 'Maximum depth',
+ // 43.SVMPanel
+ 'svm.kernel.placeholder': 'Select a Kernel',
+ // 44.FeatureSelectionForm
+ 'featureSelection.fitnessFunction': 'Fitness function',
+ 'featureSelection.searchOptimalClusters': 'Search for the optimal number of clusters (soon)',
+ 'featureSelection.maxIterations': 'Max iterations',
+ // 45.FeatureSelectionStep1
+ 'featureSelectionStep1.headerTitle': 'Biomarkers',
+ 'featureSelectionStep1.searchPlaceholder': 'Search by name',
+ // 46.FeatureSelectionStep3
+ 'featureSelectionStep3.blindSearch': 'Blind Search',
+ 'featureSelectionStep3.expertMode': 'Expert mode',
+ 'featureSelectionStep3.geneticAlgorithms': 'Genetic Algorithms',
+ // 47.CrossValidationInput
+ 'crossValidation.integerPlaceholder': 'An integer number',
+ // 48.FeatureSelectionPanel
+ 'featureSelectionPanel.tag': 'Tag',
+ 'featureSelectionPanel.step1': 'Step 1',
+ 'featureSelectionPanel.step2': 'Step 2: Datasets',
+ 'featureSelectionPanel.step3': 'Step 3: Feature selection',
+ 'featureSelectionPanel.selectBiomarker': 'Select biomarker',
+ 'featureSelectionPanel.selectedBiomarker': 'Selected {biomarker}',
+ // 49.FeatureSelectionMenu
+ // 50.NewBiomarkerForm
+ 'newBiomarkerForm.newBiomarker': 'New biomarker',
+ 'newBiomarkerForm.cannotEditMolecules': 'Cannot edit molecules',
+ 'newBiomarkerForm.cannotEditMoleculesDescription': 'This biomarker contains associated models and validations, so its molecules cannot be modified. To change its molecules consider cloning this biomarker and working with its copy.',
+ 'newBiomarkerForm.selectMolecule': 'Select molecule',
+ 'newBiomarkerForm.invalidMoleculesWarning': 'Some molecules (in orange) from the panels were not found in our database.',
+ 'newBiomarkerForm.ambiguousMoleculesWarning': 'There are ambiguous molecules (in yellow). Please select the appropriate ones in the panels.',
+ 'newBiomarkerForm.ignoreMoleculesWarnings': 'Ignore molecules with warnings',
+ 'newBiomarkerForm.ignoreMoleculesInfo': 'This message does not indicate an error in your data, but that these molecules were not found during validation. This may be due to outdated data or different nomenclatures. If you are sure there are no corrections to be made and wish to continue saving the biomarker, check the box to enable submission.',
+ 'newBiomarkerForm.sendForm': 'Send form',
+ 'newBiomarkerForm.resetForm': 'Reset form',
+ 'newBiomarkerForm.resetFormDescription': 'You are going to reset the form and clean all the inserted data.',
+ // 51.SelectDropDownSingleMolecule
+ 'selectDropDownSingleMolecule.selectMolecules': 'Select molecules',
+ 'selectDropDownSingleMolecule.noResults': 'Molecule not found',
+ 'selectDropDownSingleMolecule.ignoreAlias': "Don't use proposed alias",
+ 'selectDropDownSingleMolecule.ignoreAliasInfo': 'If checked, the molecule will be added to the biomarker with the name found in the query.',
+ 'selectDropDownSingleMolecule.searchInfo': 'This search engine will display molecules starting with the search criteria and, if necessary, the validated alias found in our database. The latter will be added to the biomarker. If you want to enter the molecule as it was found, check the box below.',
+ // 52.TextAreaMolecules
+ 'textAreaMolecules.insertMolecules': 'Insert molecules',
+ // 53.BiomarkerDetailsMenu
+ 'biomarkerDetailsMenu.moleculesDetails': 'Molecules details',
+ 'biomarkerDetailsMenu.moleculesDetailsInfo': 'Details of the molecules that make up the biomarker',
+ 'biomarkerDetailsMenu.trainedModels': 'Trained models',
+ 'biomarkerDetailsMenu.trainedModelsInfo': 'Panel to list and train Machine Learning models from genomic and epigenomic information. These models allow statistical validation of the prognostic/predictive power of the biomarker or inference on new data.',
+ 'biomarkerDetailsMenu.statisticalValidations': 'Statistical validations',
+ 'biomarkerDetailsMenu.statisticalValidationsInfo': 'Perform statistical validations from previously trained Machine Learning models.',
+ 'biomarkerDetailsMenu.inference': 'Inference',
+ 'biomarkerDetailsMenu.inferenceInfo': 'Perform inference on new genomic and epigenomic data from previously trained Machine Learning models.',
+ 'biomarkerDetailsMenu.featureSelectionSummary': 'Feature Selection summary',
+ 'biomarkerDetailsMenu.featureSelectionSummaryInfo': 'Feature Selection process details.',
+ // 54.BiomarkerOriginLabel
+ 'biomarkerOriginLabel.manual': 'Manual',
+ 'biomarkerOriginLabel.featureSelection': 'Feature Selection',
+ // 55.SharedInstitutionsBiomarker.tsx
+ 'sharedInstitutionsBiomarker.header': 'Shared institutions',
+ 'sharedInstitutionsBiomarker.selectPlaceholder': 'Select an institution to share',
+ 'sharedInstitutionsBiomarker.addInstitution': 'Add institution',
+ 'sharedInstitutionsBiomarker.removeInstitution': 'Remove institution',
+ 'sharedInstitutionsBiomarker.confirm.share.header': 'Share biomarker',
+ 'sharedInstitutionsBiomarker.confirm.share.content': 'Are you sure you want to share this biomarker with the selected institution?',
+ 'sharedInstitutionsBiomarker.confirm.stopShare.header': 'Stop sharing with institution',
+ 'sharedInstitutionsBiomarker.confirm.stopShare.content': 'Are you sure you want to stop sharing this biomarker with this institution?',
+ 'sharedInstitutionsBiomarker.users.title': '{institutionName} users',
+ 'sharedInstitutionsBiomarker.users.column': 'User name',
+ 'sharedInstitutionsBiomarker.users.searchPlaceholder': 'Search by user name',
+ // 56.SharedUsersBiomarker.tsx
+ 'sharedUsersBiomarker.header': 'Shared users',
+ 'sharedUsersBiomarker.selectPlaceholder': 'Select a user to share',
+ 'sharedUsersBiomarker.addUser': 'Add user',
+ 'sharedUsersBiomarker.removeUser': 'Remove user',
+ 'sharedUsersBiomarker.confirm.share.header': 'Share biomarker',
+ 'sharedUsersBiomarker.confirm.share.content': 'Are you sure you want to share this biomarker with the selected user?',
+ 'sharedUsersBiomarker.confirm.stopShare.header': 'Stop sharing with user',
+ 'sharedUsersBiomarker.confirm.stopShare.content': 'Are you sure you want to stop sharing this biomarker with this user?',
+ // 58.NewCGDSDatasetForm
+ 'cgdsDatasetForm.filePath.placeholder': 'File Path',
+ 'cgdsDatasetForm.separator.placeholder': 'Select separator',
+ 'cgdsDatasetForm.separator.label': 'Separator',
+ 'cgdsDatasetForm.separator.comma': 'Comma',
+ 'cgdsDatasetForm.separator.semicolon': 'Semicolon',
+ 'cgdsDatasetForm.separator.tab': 'Tab',
+ 'cgdsDatasetForm.separator.colon': 'Colon',
+ 'cgdsDatasetForm.separator.whitespace': 'White space',
+ 'cgdsDatasetForm.observation.placeholder': 'Observation',
+ 'cgdsDatasetForm.headerIndex.placeholder': 'Header Row Index (0 indexed)',
+ 'cgdsDatasetForm.headerIndex.help': 'Row indexes are 0-indexed',
+ 'cgdsDatasetForm.mongoName.placeholder': "Mongo Collection's name",
+ 'cgdsDatasetForm.icon.add': 'Add dataset',
+ 'cgdsDatasetForm.icon.remove': 'Remove dataset',
+ // 59.NewCGDSStudyForm
+ 'cgdsStudyForm.header': 'Add specification of CGDS Study',
+ 'cgdsStudyForm.url.placeholder': 'URL (tar.gz/zip)',
+ 'cgdsStudyForm.urlInfo.placeholder': 'URL of extra info',
+ 'cgdsStudyForm.datasets.header': 'CGDS Datasets',
+ 'cgdsStudyForm.dataset.methylation': 'Methylation',
+ 'cgdsStudyForm.dataset.clinicalPatients': 'Clinical Patients',
+ 'cgdsStudyForm.dataset.clinicalSamples': 'Clinical Samples',
+ 'cgdsStudyForm.requiredField': 'Required field',
+ 'cgdsStudyForm.syncWarning': 'In order to have the data available, you must perform the synchronization at least once',
+ 'cgdsStudyForm.addStudy': 'Add study',
+ 'cgdsStudyForm.editStudy': 'Edit study',
+ // 60.BoxplotsCommons
+ 'boxPlotTooltip.min': 'Min',
+ 'boxPlotTooltip.firstQuartile': 'First quartile',
+ 'boxPlotTooltip.median': 'Median',
+ 'boxPlotTooltip.thirdQuartile': 'Third quartile',
+ 'boxPlotTooltip.max': 'Max',
+ 'boxPlotTooltip.mean': 'Mean',
+ 'boxPlotTooltip.outliers': 'Outliers (using MAD)',
+ // 61.ClusterLabelsSetsModal
+ 'clusterLabelsSetsModal.header': 'Cluster labels sets',
+ 'clusterLabelsSetsModal.newClusterModel': 'New Cluster model',
+ 'clusterLabelsSetsModal.searchPlaceholder': 'Search by name or description',
+ // 62.NewClusterLabelsSetModal
+ 'newClusterLabelsSetModal.header': 'New Cluster labels set',
+ 'newClusterLabelsSetModal.labelsHeader': 'Labels',
+ 'newClusterLabelsSetModal.clusterId': 'Cluster ID',
+ 'newClusterLabelsSetModal.label': 'Label',
+ 'newClusterLabelsSetModal.addLabel': 'Add label',
+ 'newClusterLabelsSetModal.deleteLabel': 'Delete label',
+ 'newClusterLabelsSetModal.color': 'Color',
+ // 63.NewPredictionRangeLabelsSetModal
+ 'newPredictionRangeLabelsSetModal.header': 'New Cluster labels sets',
+ 'newPredictionRangeLabelsSetModal.subHeader': 'New PredictionRangeLabelsSet',
+ 'newPredictionRangeLabelsSetModal.labelsHeader': 'Labels',
+ 'newPredictionRangeLabelsSetModal.minValue': 'Min value',
+ 'newPredictionRangeLabelsSetModal.maxValue': 'Max value',
+ 'newPredictionRangeLabelsSetModal.label': 'Label',
+ 'newPredictionRangeLabelsSetModal.deleteLabel': 'Delete label',
+ 'newPredictionRangeLabelsSetModal.addLabel': 'Add label',
+ 'newPredictionRangeLabelsSetModal.color': 'Color',
+ 'newPredictionRangeLabelsSetModal.error.maxValue': 'Max value must be greater than min value',
+ 'newPredictionRangeLabelsSetModal.error.overlap': 'Ranges overlaps with label "{label}" (position {position})',
+ // 64.PredictionRangeLabelsSetModal
+ 'predictionRangeLabelsSetModal.header': 'Prediction range labels sets',
+ 'predictionRangeLabelsSetModal.newModel': 'New prediction range labels set',
+ 'predictionRangeLabelsSetModal.searchPlaceholder': 'Search by name or description',
+ // 65.PredictionRangeLabelsSetSelect
+ 'predictionRangeLabelsSetSelect.label': 'Use a range label',
+ 'predictionRangeLabelsSetSelect.placeholder': 'Use range labels',
+ // 66.EditIcon.tsx
+ 'common.edit': 'Edit',
+ // 67.PaginatedTable.tsx
+ 'paginatedTable.loading': 'Loading...',
+ 'paginatedTable.searchLabel': 'Name/Description',
+ 'paginatedTable.entries': 'Entries',
+ // 68.SourceSelectors.tsx
+ 'sourceSelectors.clinicalProfile': 'Clinical profile',
+ 'sourceSelectors.mRNAProfile': 'mRNA profile',
+ 'sourceSelectors.mirnaProfile': 'Mirna profile',
+ 'sourceSelectors.cnaProfile': 'CNA profile',
+ 'sourceSelectors.methylationProfile': 'Methylation profile',
+ // 69.SwitchPublicButton.tsx
+ 'switchPublicButton.makePrivate': 'Make {nameEntity} private',
+ 'switchPublicButton.makePublic': 'Make {nameEntity} public',
+ 'switchPublicButton.confirmMakePrivate': 'Are you sure to make the {nameEntity} private?',
+ 'switchPublicButton.confirmMakePublic': 'Are you sure to make the {nameEntity} public?',
+ // 70.TableCellSources.tsx
+ 'tableCellSources.downloadClinical': 'Download source clinical file',
+ 'tableCellSources.downloadMrna': 'Download source mRNA file',
+ 'tableCellSources.downloadMirna': 'Download source miRNA file',
+ 'tableCellSources.downloadCna': 'Download source CNA file',
+ 'tableCellSources.downloadMethylation': 'Download source methylation file',
+ // 71.TagForm.tsx
+ 'tagForm.newTag': 'New tag',
+ // 72.TagLabel.tsx
+ 'tagLabel.noTagAssigned': 'No tag assigned',
+ // 73.TryAgainSegment.tsx
+ 'tryAgainSegment.message': 'Something went wrong, please try again',
+ 'tryAgainSegment.button': 'Try Again',
+ // 74.DifferentialExpressionForm.tsx
+ 'differentialExpressionForm.header': 'New Differential Expression',
+ 'differentialExpressionForm.samplesMRNA': 'Samples mRNA: {count}',
+ 'differentialExpressionForm.samplesClinical': 'Samples clinical: {count}',
+ 'differentialExpressionForm.samplesInCommon': 'Samples in common: {count}',
+ 'differentialExpressionForm.thresholdPercentile': 'Threshold percentile: {value}',
+ 'differentialExpressionForm.thresholdPercentile.info': 'Percentile threshold for filtering low-expression genes (default 0.15)',
+ 'differentialExpressionForm.thresholdStd': 'Threshold std: {value}',
+ 'differentialExpressionForm.thresholdStd.info': 'Variance threshold for gene filtering (default 1e-4)',
+ 'differentialExpressionForm.top': 'Top: {value}',
+ 'differentialExpressionForm.top.info': 'Most significant number of genes to keep as result',
+ 'differentialExpressionForm.editExperiment': 'Edit experiment',
+ 'differentialExpressionForm.createExperiment': 'Create experiment',
+ 'differentialExpressionForm.cancelEdit': 'Cancel edit',
+ 'differentialExpressionForm.resetForm': 'Reset form',
+ 'differentialExpressionForm.successCreated': 'Differential Expression experiment created successfully!',
+ 'differentialExpressionForm.successUpdated': 'Differential Expression experiment updated successfully!',
+ 'differentialExpressionForm.errorCreating': 'Error creating Differential Expression experiment!',
+ 'differentialExpressionForm.errorUpdating': 'Error to update Differential Expression experiment!',
+ // 75.DifferentialExpressionInputClinicalAttribute.tsx
+ 'differentialExpressionInputClinicalAttribute.label': 'Group by clinical attribute',
+ 'differentialExpressionInputClinicalAttribute.placeholder': 'Clinical attribute to group by',
+ // 76.DifferentialExpressionModalResults.tsx
+ 'differentialExpressionModalResults.header': 'Differential Expression Analysis Results - {name}',
+ 'differentialExpressionModalResults.tab.volcanoPlot': 'Volcano Plot',
+ // 77.DifferentialExpressionModalResultsTableView.tsx
+ 'diffExpResultsTable.logFoldThreshold': 'Log Fold threshold',
+ 'diffExpResultsTable.headerTitle': 'Differential Expression Results',
+ 'diffExpResultsTable.noLogFold': 'No Log Fold filter',
+ 'diffExpResultsTable.pValueThreshold': 'P-value threshold',
+ 'diffExpResultsTable.noPValue': 'No P-value filter',
+ 'diffExpResultsTable.gene': 'Gene',
+ 'diffExpResultsTable.adjPValue': 'Adjusted p-value',
+ 'diffExpResultsTable.avgExpression': 'Average expression',
+ 'diffExpResultsTable.bStatistic': 'B statistic',
+ 'diffExpResultsTable.logFoldChange': 'Log Fold Change',
+ 'diffExpResultsTable.pValue': 'P-value',
+ 'diffExpResultsTable.tStatistic': 'T statistic',
+ 'diffExpResultsTable.downloadCSV': 'Download results in a CSV file',
+ 'diffExpResultsTable.searchPlaceholder': 'Search by gene',
+ // 78.DifferentialExpressionModalResultsVolcanoPlot
+ 'differentialExpression.volcanoPlot.title': 'Volcano Plot',
+ 'differentialExpression.volcanoPlot.fcThreshold': '|log2FC| threshold',
+ 'differentialExpression.volcanoPlot.pValueThreshold': 'p-value threshold',
+ 'differentialExpression.volcanoPlot.showThresholds': 'Show thresholds',
+ // 79.DifferentialExpressionPanel
+ 'differentialExpression.panel.noMethod': 'No method',
+ 'differentialExpression.panel.selectMethod': 'Select an existing method',
+ 'differentialExpression.panel.method': 'Method',
+ 'differentialExpression.panel.headerTitle': 'Differential Expressions Analyses',
+ 'differentialExpression.panel.nameDescription': 'Name/Description',
+ 'differentialExpression.panel.searchByNameDescription': 'Search by name/description',
+ 'differentialExpression.panel.stopSuccess': 'Differential Expression experiment stopped successfully!',
+ 'differentialExpression.panel.stopError': 'Error stopping Differential Expression experiment!',
+ 'differentialExpression.panel.deleteSuccess': 'Differential Expression experiment deleted successfully!',
+ 'differentialExpression.panel.deleteError': 'Error deleting Differential Expression experiment!',
+ 'differentialExpression.panel.downloadMrnaSource': 'Download source mRNA file',
+ 'differentialExpression.panel.downloadClinicalSource': 'Download Clinical source file',
+ 'differentialExpression.panel.publicVisible': 'All users of the platform can see this experiment',
+ 'differentialExpression.panel.publicHidden': 'If this is checked all the users in the platform can see (but not edit or remove) this element',
+ 'differentialExpression.panel.seeResults': 'See results',
+ 'differentialExpression.panel.stopExperiment': 'Stop experiment',
+ 'differentialExpression.panel.stopExperimentTitle': 'Stop Experiment',
+ 'differentialExpression.panel.stopExperimentConfirm': 'Are you sure to stop experiment?',
+ 'differentialExpression.panel.deleteExperiment': 'Delete experiment',
+ // 80.Volcano Plot
+ 'differentialExpression.volcanoPlot.significant': 'Significant',
+ 'differentialExpression.volcanoPlot.notSignificant': 'Not Significant',
+ 'differentialExpression.volcanoPlot.logFoldChange': 'log2(Fold Change)',
+ 'differentialExpression.volcanoPlot.logPValue': '-log10(P-value)',
+ // 81.FAQ
+ 'faq.pageTitle': 'Frequently Asked Questions',
+ 'faq.whatIs.question': 'What is Multiomix?',
+ 'faq.whatIs.answer': 'Multiomix is a cloud-based, open-source platform for investigating genomic and epigenomic events associated with the modulation of gene expression, with a focus on biomarker discovery and multi-omic analysis in cancer. It integrates data retrieval, aggregation, analysis, and visualization functions for both public and user-uploaded data.',
+ 'faq.whatIs.link': 'Paper',
+ 'faq.analysisTypes.question': 'What kind of analysis can I do in Multiomix?',
+ 'faq.analysisTypes.answer': 'Multiomix allows you to run correlation analyses between mRNA and other non-mRNA omic layers, particularly miRNA, DNA methylation, and CNA. It also includes survival analysis, statistical validations, model training, and inference on new datasets. In terms of biomarkers, the platform enables identifying, managing, and evaluating signatures composed of different omic variables, exploring their prognostic or predictive value, training models on those biomarkers, and reusing them for validation and inference on new cohorts.',
+ 'faq.pipelines.question': 'What main pipelines and statistical methods does the platform offer?',
+ 'faq.pipelines.p1': 'The platform provides three core pipelines: miRNA-mRNA, DNA methylation-mRNA, and CNA-mRNA. In these workflows, users select datasets, filters, correlation method, and p-value adjustment, then explore results alongside clinical and follow-up information.',
+ 'faq.pipelines.p2': 'For correlation, Multiomix supports Pearson, Spearman, and Kendall. For multiple testing correction, it supports Benjamini-Hochberg, Benjamini-Yekutieli, and Bonferroni, among others. Survival analyses such as Kaplan-Meier and Log-rank are also included to estimate the biological impact of detected events.',
+ 'faq.pipelines.p3': 'A dedicated panel for biomarker management, optimization, and evaluation supports biomarkers composed of mRNA, miRNA, CNA, and methylation sites. It allows training clustering, Survival SVM, and Random Survival Forest models to assess prognostic or predictive power, and reusing already trained models for new validations and inferences without retraining from scratch. For existing biomarkers, the platform also offers optimization through multiple feature selection methods.',
+ 'faq.uploadData.question': 'Can I upload my own data?',
+ 'faq.uploadData.answer': 'Yes. Multiomix allows you to upload your own datasets in a validated manner, with format and consistency checks. It also offers batch uploads for large datasets and an interactive table with filters, search, pagination, sorting, and tagging to manage your data.',
+ 'faq.datasetsPublic.question': 'Does Multiomix include ready-to-use public data?',
+ 'faq.datasetsPublic.answer': 'Yes. The platform includes preloaded datasets retrieved programmatically from cBioPortal. This allows you to work with both public and private data in the same environment.',
+ 'faq.datasetsPreprocessing.question': 'How are cBioPortal datasets incorporated and preprocessed?',
+ 'faq.datasetsPreprocessing.p1': 'Datasets from cBioPortal are synchronized regularly to ensure data consistency. If there is an update that we miss, users can contact us directly. Duplicate molecules are removed to keep the dataset clean. Samples without information for a given molecule in a biomarker are excluded from trained models, statistical validations, feature selection experiments, and inference steps.',
+ 'faq.datasetsPreprocessing.p2': 'Clinical data also undergo preprocessing: cases with NaN, empty or Null values are filtered out. Additionally, cases with an event but survival time equal to zero are excluded (pending clarification from cBioPortal).',
+ 'faq.expertise.question': 'Is Multiomix only for expert bioinformaticians?',
+ 'faq.expertise.answer': 'Not necessarily. Multiomix was designed to lower technical barriers and provide an accessible experience for non-expert users as well, without sacrificing analytical rigor. Its goal is to bring biomarker discovery closer to a broader range of research profiles through a friendly interface, clear documentation, and usage guides, within an open and technology-democratization-oriented approach.',
+ 'faq.performance.question': 'What makes Multiomix different in terms of correlation analysis performance?',
+ 'faq.performance.answer': 'For large-scale correlation analysis, Multiomix developed its own tool called GGCA, implemented in Rust to improve performance and memory usage.',
+ 'faq.metaheuristics.question': 'How does Multiomix accelerate metaheuristic execution for feature selection?',
+ 'faq.metaheuristics.answer': 'Multiomix incorporates distributed computing optimizations over Apache Spark to accelerate the evaluation of metaheuristic agents in feature selection processes. It also includes internally developed distribution strategies designed to maximize the use of available resources and achieve the best possible performance.',
+ 'faq.metaheuristics.link': 'Source',
+ 'faq.integrations.question': 'What ecosystem tools does Multiomix integrate with?',
+ 'faq.integrations.answer': 'Multiomix relies on BioAPI and Modulector for part of its functionality. Both platforms act as abstraction layers for standardized access to biological data. BioAPI exposes gene nomenclature, expression, and pathway information through a REST API, while Modulector centralizes miRNA, gene, and methylation site data, and offers services related to PubMed evidence and news.',
+ 'faq.technologies.question': 'What technologies does Multiomix use internally?',
+ 'faq.technologies.answer': 'Multiomix is built as a Python/Rust web application. It uses Django on the backend, React with TypeScript on the frontend, PostgreSQL for annotations, MongoDB for preloaded datasets, and Redis/WebSocket for asynchronous execution and notifications. Celery is used for task queues, with dependencies on Modulector and BioAPI.',
+ 'faq.privacy.question': 'How is user-uploaded data privacy handled?',
+ 'faq.privacy.answer': 'Uploaded data is securely stored and only accessible to the uploading user. Once deleted, the data is permanently removed from our servers and cannot be recovered. No third parties have access to private user data.',
+ 'faq.installation.question': 'Can I install Multiomix locally?',
+ 'faq.installation.answer': 'Yes. Multiomix can be deployed locally and its official repository includes installation and development instructions, as well as support for quick deployments with Docker and complementary installation of BioAPI and Modulector. The project is distributed under the GPL-3.0 license, which promotes transparency, source code access, adaptability to specific needs, and open community collaboration.',
+ 'faq.licenses.question': 'Libraries and tools with Licenses',
+ 'faq.licenses.answer': 'For legal and transparency reasons, we provide a list of third-party libraries and tools used in this platform, along with their respective licenses. This ensures compliance and acknowledgment of the open-source community contributions that power our ecosystem.',
+ 'faq.footer.links.siteMap': 'Site Map',
+ 'faq.footer.links.contact': 'Contact Us',
+ 'faq.footer.links.terms': 'Terms and Conditions',
+ 'faq.footer.links.privacy': 'Privacy Policy',
+ // 82.FilesManager
+ 'files.manager.title': 'File Manager',
+ 'files.manager.input.label': 'Add a new file',
+ 'files.manager.table.name': 'Name',
+ 'files.manager.table.description': 'Description',
+ 'files.manager.table.type': 'Type',
+ 'files.manager.table.date': 'Date',
+ 'files.manager.table.institutions': 'Institutions',
+ 'files.manager.table.tag': 'Tag',
+ 'files.manager.table.public': 'Public',
+ 'files.manager.table.actions': 'Actions',
+ 'files.manager.filter.tag.placeholder': 'Select existing Tag',
+ 'files.manager.filter.visibility.all': 'All',
+ 'files.manager.filter.visibility.private': 'Private',
+ 'files.manager.search.placeholder': 'Search by name',
+ 'files.manager.delete.tag.title': 'Delete tag',
+ 'files.manager.delete.tag.confirm': 'Are you sure you want to delete the Tag "{tagName}"?',
+ 'files.manager.delete.file.title': 'Delete file',
+ 'files.manager.delete.file.confirm': 'Are you sure you want to delete the file {fileName}?',
+ 'files.manager.delete.file.warning.clinical': 'This file will be UNLINKED from all the associated experiments',
+ 'files.manager.delete.file.warning.default': 'All the associated experiments to this file will be DELETED',
+ 'files.manager.upload.unloadWarning': 'A file is being uploaded. If you close the tab the upload will be canceled.',
+ 'files.manager.error.invalidFormat': 'The file has an incorrect format: all columns except the index must be numerical data',
+ 'files.manager.tooltip.sharedWith': 'This dataset is shared with {list}',
+ 'files.manager.tooltip.publicVisible': 'All users of the platform can see this file',
+ 'files.manager.tooltip.privateVisibility': 'If this is checked all the users in the platform can see (but not edit or remove) this element',
+ 'files.manager.tooltip.indexColumn': 'The column "{columnName}" will be used as index',
+ 'files.manager.tooltip.edit': 'Edit',
+ 'files.manager.tooltip.download': 'Download file',
+ 'files.manager.tooltip.nanWarning': 'The dataset contains NaN values',
+ // Agregados
+ // BiomarkersPanel
+ 'biomarkersPanel.stopExperiment.header': 'Stop experiment',
+ 'biomarkersPanel.stopExperiment.content': 'Are you sure you want to stop the experiment {name}?',
+ 'biomarkersPanel.deleteModal.header': 'Delete Biomarker',
+ 'biomarkersPanel.deleteModal.content': 'Are you sure you want to delete the Biomarker {name}?',
+ 'biomarkersPanel.cloneModal.header': 'Clone Biomarker',
+ 'biomarkersPanel.cloneModal.content': 'Are you sure you want to clone the Biomarker "{name}"?',
+ 'biomarkersPanel.cloneModal.button': 'Clone',
+ 'biomarkersPanel.table.headerTitle': 'Biomarkers',
+ 'biomarkersPanel.table.searchPlaceholder': 'Search by name',
+ 'biomarkersPanel.table.column.tag': 'Tag',
+ 'biomarkersPanel.table.column.origin': 'Origin',
+ 'biomarkersPanel.table.column.public': 'Public',
+ 'biomarkersPanel.table.column.shared': 'Shared',
+ 'biomarkersPanel.table.addButton.title': 'Add new Biomarker',
+ 'biomarkersPanel.icon.sharedInstitutions': 'Shared institutions',
+ 'biomarkersPanel.icon.sharedUsers': 'Shared users',
+ 'biomarkersPanel.icon.clone': 'Clone biomarker',
+ 'biomarkersPanel.icon.public': 'All users of the platform can see this experiment',
+ 'biomarkersPanel.icon.notPublic': 'If this is checked all the users in the platform can see (but not edit or remove) this element',
+ 'biomarkersPanel.confirmModal.loseData.header': 'You are going to lose all the data inserted',
+ 'biomarkersPanel.confirmModal.loseData.content': 'Are you sure?',
+ 'biomarkersPanel.alert.errorCreating': 'Error creating biomarker!',
+ 'biomarkersPanel.alert.errorEditing': 'Error editing biomarker!',
+ 'biomarkersPanel.alert.successCreating': 'Biomarker created successfully',
+ 'biomarkersPanel.alert.successEditing': 'Biomarker edited successfully',
+ 'biomarkersPanel.alert.successSubmitting': 'Experiment submitted!',
+ 'biomarkersPanel.tags.noTag': 'No tag',
+ 'biomarkersPanel.tags.label': 'Tag',
+ 'biomarkersPanel.tags.placeholder': 'Select an existing Tag',
+
+}
diff --git a/src/frontend/static/frontend/src/locales/es.ts b/src/frontend/static/frontend/src/locales/es.ts
new file mode 100644
index 00000000..ae6aeba1
--- /dev/null
+++ b/src/frontend/static/frontend/src/locales/es.ts
@@ -0,0 +1,789 @@
+export default {
+ // Common actions
+ 'common.cancel': 'Cancelar',
+ 'common.delete': 'Eliminar',
+ 'common.stop': 'Detener',
+ 'common.save': 'Guardar',
+ 'common.close': 'Cerrar',
+ 'common.actions': 'Acciones',
+ 'common.confirm': 'Confirmar',
+ 'common.sample': 'Muestra',
+ 'common.goBack': 'Volver',
+ 'common.search': 'Buscar',
+ 'common.details': 'Detalles',
+ 'common.noDetails': 'No se encontraron detalles',
+ 'common.name': 'Nombre',
+ 'common.description': 'Descripción',
+ 'common.requiredField': 'Campo obligatorio',
+ 'common.model': 'Modelo:',
+ 'common.date': 'Fecha',
+ 'common.datasets': 'Conjuntos de datos',
+ // Common Labels
+ 'common.algorithm': 'Algoritmo',
+ 'common.nClusters': 'Número de clusters',
+ 'common.metric': 'Métrica',
+ 'common.scoringMethod': 'Método de puntuación',
+ 'common.randomState': 'Estado aleatorio',
+ 'common.penalizer': 'Penalizador',
+ 'common.integerPlaceholder': 'Un número entero',
+ 'common.numberOfIterations': 'Número de iteraciones',
+ 'common.coefficient': 'Coeficiente',
+ // Forms and steps
+ 'common.basicData': 'Datos básicos',
+ 'common.descriptionOptional': 'Descripción (opcional)',
+ 'common.continue': 'Continuar',
+ // common Tables and states
+ 'common.state': 'Estado',
+ 'common.cluster': 'Cluster',
+ 'common.relations': 'Relaciones',
+
+ // Auth/usuario
+ 'auth.login': 'Iniciar sesión',
+ 'auth.greeting': 'Hola, {username}',
+ 'auth.editProfile': 'Editar perfil',
+ 'auth.logout': 'Salir',
+
+ // Menús
+ 'menu.analysis': 'Análisis',
+ 'menu.gem': 'GEM',
+ 'menu.gem.tooltip': 'Modulación de Expresión Génica',
+ 'menu.biomarkers': 'Biomarcadores',
+ 'menu.datasets': 'Conjuntos de datos',
+ 'menu.multiomix': 'Multiomix',
+ 'menu.cbioportal': 'cBioPortal',
+ 'menu.institutions': 'Instituciones',
+ 'menu.admin': 'Administración',
+ 'menu.admin.genes': 'Base de datos: Genes',
+ 'menu.about': 'Sobre nosotros',
+ 'menu.faq': 'Preguntas frecuentes',
+ 'menu.opensource': 'Código abierto',
+
+ // About us
+ 'about.description': 'Multiomix es el resultado del trabajo interdisciplinario entre miembros de las siguientes instituciones científicas:',
+ 'about.institution.caeti': 'CAETI - Universidad Abierta Interamericana',
+ 'about.institution.ciniba': 'CINIBA - Facultad de Ciencias Médicas - UNLP',
+ 'about.institution.lidi': 'LIDI - Facultad de Informática - UNLP',
+
+ 'about.coordination': 'Coordinación del proyecto:',
+
+ 'about.members.title': 'Miembros del proyecto:',
+ 'about.members.main': 'Contribuyente principal:',
+ 'about.members.collaborators': 'Colaboradores:',
+
+ 'about.contact.title': 'Contacto:',
+ 'about.contact.questions': 'Para preguntas o sugerencias, contáctenos:',
+ 'about.contact.institutions': 'También puede contactarnos para crear su institución de investigación. Esto permitirá a los investigadores compartir conjuntos de datos dentro de Multiomix.',
+
+ // BIOMARKERS
+
+ // BiomarkerInferenceExperimentsPanel.tsx
+ 'inference.experiment.title': 'Experimento de interferencia "{name}"',
+ // 2.InferenceExperimentClinicalAttributeSelect.tsx
+ 'inference.clinicalAttribute.label': 'Agrupar por atributo clínico',
+ 'inference.clinicalAttribute.placeholder': 'Atributo clínico para agrupar',
+ // 3.InferenceExperimentResultMetrics.tsx
+ 'inference.metrics.title': 'Métricas de "{name}"',
+ 'inference.model': 'Modelo',
+ // 5.InferenceExperimentsTable.tsx
+ 'inference.stop.title': 'Detener experimento de inferencia',
+ 'inference.stop.confirm': '¿Estás segura de que quieres detener el experimento de inferencia "{name}"?',
+ 'inference.stop.cancel': '{common.cancel}',
+ 'inference.stop.button': '{common.stop}',
+
+ 'inference.delete.title': 'Eliminar experimento',
+ 'inference.delete.confirm': '¿Estás segura de que quieres eliminar el experimento de inferencia "{name}"?',
+ 'inference.delete.cancel': '{common.cancel}',
+ 'inference.delete.button': '{common.delete}',
+
+ 'inference.table.title': 'Experimentos de inferencia',
+ 'inference.table.columns.model': 'Modelo',
+ 'inference.table.columns.dataset': 'Conjuntos de datos',
+ 'inference.table.columns.actions': 'Acciones',
+
+ 'inference.search.placeholder': 'Buscar por nombre o descripción',
+
+ 'inference.new.title': 'Nuevo experimento de inferencia',
+ 'inference.results.title': 'Ver resultados',
+ 'inference.results.tooltip': 'Eliminar experimento',
+ // 6.NewInferenceExperimentModal.tsx
+ 'inference.newInference.title': 'Crear nuevo experimento de inferencia',
+ 'inference.new.step1': 'Paso 1: Modelo entrenado',
+ 'inference.new.step2': 'Paso 2: Conjuntos de datos de moléculas',
+ // 7.SamplesAndGroupsInferenceTable.tsx
+ 'inference.table.download.tooltip': 'Descargar resultados en un archivo CSV',
+ 'inference.table.filter.cluster.placeholder': 'Filtrar por grupo',
+ 'inference.table.addClusterLabels': 'Agregar etiquetas de grupo',
+ // 8.SamplesAndTimeInferenceCharts.tsx
+ 'inference.charts.noAttribute': 'No se seleccionó ningún atributo clínico',
+ 'inference.charts.selectAttribute': 'Por favor, selecciona uno en el selector de la derecha.',
+ // 9.SamplesAndTimeInferenceTable.tsx
+ 'inference.timeTable.columns.predictedTime': 'Tiempo predicho',
+ 'inference.timeTable.filter.range.label': 'Rango',
+ 'inference.timeTable.filter.range.placeholder': 'Filtrar por rango',
+ 'inference.timeTable.menu.table': 'Tabla',
+ 'inference.timeTable.menu.charts': 'Gráficos',
+ 'inference.timeTable.menu.table.info': 'Tabla con todas las muestras y su tiempo de riesgo/supervivencia predicho',
+ 'inference.timeTable.menu.charts.info': 'Muestra gráficos con las muestras y su tiempo de riesgo/supervivencia predicho agrupado por alguna condición',
+ 'inference.timeTable.addRangeLabels': 'Agregar etiquetas de rango',
+ // 10.molecules/GeneOntologyCytoscapeChart.tsx
+ 'geneOntology.form.ontologyType': 'Tipo de ontología',
+ 'geneOntology.form.generalDepth': 'Profundidad general',
+ 'geneOntology.form.hierarchicalDepth': 'Profundidad jerárquica hacia hijos',
+ 'geneOntology.form.toRoot': 'Hasta la raíz',
+ 'geneOntology.relation.hasPart': 'Tiene parte',
+ 'geneOntology.relation.isA': 'Es un',
+ 'geneOntology.relation.partOf': 'Parte de',
+ 'geneOntology.relation.regulates': 'Regula',
+ // 11.GeneOntologyPanel
+ 'geneOntology.panel.filterType': 'Tipo de filtro',
+ 'geneOntology.panel.filterType.intersection': 'Intersección',
+ 'geneOntology.panel.filterType.union': 'Unión',
+ 'geneOntology.panel.filterType.enrichment': 'Enriquecimiento',
+ 'geneOntology.panel.pValueThreshold': 'Umbral de valor p',
+ 'geneOntology.panel.correctionMethod': 'Método de corrección',
+ 'geneOntology.panel.correctionMethod.analytical': 'Analítico',
+ 'geneOntology.panel.correctionMethod.bonferroni': 'Bonferroni',
+ 'geneOntology.panel.correctionMethod.falseDiscoveryRate': 'Tasa de descubrimiento falso',
+ 'geneOntology.panel.relationType': 'Tipo de relación',
+ 'geneOntology.panel.relationType.enables': 'Habilita',
+ 'geneOntology.panel.relationType.involvedIn': 'Involucrado en',
+ 'geneOntology.panel.relationType.partOf': 'Parte de',
+ 'geneOntology.panel.relationType.locatedIn': 'Ubicado en',
+ 'geneOntology.panel.ontologyType': 'Tipo de ontología',
+ 'geneOntology.panel.ontologyType.biologicalProcess': 'Proceso biológico',
+ 'geneOntology.panel.ontologyType.molecularFunction': 'Función molecular',
+ 'geneOntology.panel.ontologyType.cellularComponent': 'Componente celular',
+ 'geneOntology.panel.table.term': 'Término',
+ 'geneOntology.panel.table.ontologyType': 'Tipo de ontología',
+ // 12GENES.ActionableCancerGenesPanel.tsx
+ 'actionableGenes.panel.title': 'Panel de genes de cáncer accionables',
+ // 13.GeneAssociationsNetworkPanel
+ 'geneAssociations.relation.fusion': 'Fusión',
+ 'geneAssociations.relation.coOccurrence': 'Co-ocurrencia',
+ 'geneAssociations.relation.experimental': 'Experimental',
+ 'geneAssociations.relation.textMining': 'Minería de texto',
+ 'geneAssociations.relation.database': 'Base de datos',
+ 'geneAssociations.relation.coExpression': 'Co-expresión',
+ 'geneAssociations.form.minCombinedScore': 'Puntuación combinada mínima',
+ 'geneAssociations.infoPopup.text': 'La puntuación combinada se calcula combinando las probabilidades de los diferentes canales de evidencia y se corrige por la probabilidad de observar una interacción al azar. Para una descripción más detallada consulte von Mering, et al. Nucleic Acids Res. 2005',
+ // 14.GeneInformation
+ 'geneInformation.context.gene': 'para este gen',
+ 'geneInformation.summary': 'Resumen',
+ // 15.MetabolicPathwaysPanel.tsx
+ 'metabolicPathways.infoPopup': 'Lista de genes que participan en una vía para una base de datos dada',
+ 'metabolicPathways.header': 'Vías metabólicas',
+ 'metabolicPathways.selectSource': 'Selecciona una fuente',
+ 'metabolicPathways.sourcePlaceholder': 'Fuente',
+ // 16.PathwaysInformation.tsx
+ 'pathwaysInformation.context.gene': 'para este gen',
+ 'pathwaysInformation.context.pathways': 'para este gen',
+ // 17.MethylationInformation.tsx
+ 'methylationInformation.noDetails': 'No se encontraron detalles para este sitio de metilación',
+ 'methylationInformation.infoPopup.aliases': 'Alias de metilación y posición cromosómica',
+ 'methylationInformation.header': 'Información de metilación',
+ 'methylationInformation.chromosomePosition': 'Posición cromosómica:',
+ 'methylationInformation.infoPopup.ucsc': 'Lista de islas relacionadas con el sitio de metilación según la base de datos UCSC',
+ 'methylationInformation.header.ucsc': 'Islas CpG UCSC',
+ 'methylationInformation.table.cpgIsland': 'Isla CpG',
+ 'methylationInformation.table.relation': 'Relación',
+ 'methylationInformation.infoPopup.genes': 'Genes relacionados con este sitio de metilación y las regiones donde se encuentra. Estas regiones, según la base de datos NCBI RefSeq, pueden ser: 5UTR=5\' región no traducida entre el sitio de inicio de transcripción (TTS) y el sitio de inicio ATG, 3UTR=3\' región no traducida entre el codón de parada y la señal poli A, exon_#, TSS200=1-200 pb 5\' del TSS, o TS1500=200-1500 pb 5\' del TSS',
+ 'methylationInformation.header.genes': 'Genes relacionados',
+ 'methylationInformation.table.gene': 'Gen',
+ 'methylationInformation.table.regions': 'Regiones',
+ // 18.CurrentMoleculeDetails.tsx
+ 'currentMoleculeDetails.noSelection': 'Ninguna molécula seleccionada',
+ 'currentMoleculeDetails.selectOne': 'Selecciona una en el panel izquierdo',
+ // 19.MoleculesDetailsMenu.tsx
+ 'moleculesDetailsMenu.details.info': 'Detalles de {identifier} obtenidos de diferentes fuentes estandarizadas',
+ 'moleculesDetailsMenu.geneAssociations': 'Red de asociaciones génicas',
+ 'moleculesDetailsMenu.geneAssociations.info': 'Muestra la red de asociaciones génicas de los genes de este biomarcador',
+ 'moleculesDetailsMenu.geneOntology': 'Ontología génica',
+ 'moleculesDetailsMenu.geneOntology.info': 'La Ontología Génica (GO) es una herramienta poderosa para comprender los procesos biológicos, funciones moleculares y componentes celulares asociados a un gen',
+ 'moleculesDetailsMenu.diseases': 'Enfermedades',
+ 'moleculesDetailsMenu.diseases.info': 'Interacciones de la molécula con enfermedades reportadas en la literatura',
+ 'moleculesDetailsMenu.drugs': 'Fármacos',
+ 'moleculesDetailsMenu.drugs.info': 'Interacciones de la molécula con fármacos reportadas en la literatura',
+ 'moleculesDetailsMenu.miRNAGeneInteractions': 'Interacciones miRNA-Gen',
+ 'moleculesDetailsMenu.miRNAGeneInteractions.info': 'Diferentes interacciones miRNA-Gen reportadas en la literatura junto con el puntaje mirDIP y fuentes de PubMed',
+ // 20.MoleculesTable.tsx
+ 'moleculesTable.type.mrna': 'mRNA',
+ 'moleculesTable.type.mirna': 'miRNA',
+ 'moleculesTable.type.cna': 'CNA',
+ 'moleculesTable.type.methylation': 'Metilación',
+ 'moleculesTable.header.identifier': 'Identificador',
+ 'moleculesTable.header.type': 'Tipo',
+ 'moleculesTable.header.actions': 'Acciones',
+ 'moleculesTable.search.label': 'Muestra',
+ // 21.SamplesAndGroupsTable.tsx
+ 'samplesAndGroupsTable.header.sample': 'Muestra',
+ 'samplesAndGroupsTable.filter.cluster.placeholder': 'Filtrar por cluster',
+ 'samplesAndGroupsTable.search.label': 'Muestra',
+ // 22.StatisticalValidationResultBestFeatures.tsx
+ 'statValidationBestFeatures.axis.molecule': 'Molécula',
+ 'statValidationBestFeatures.context.features': 'características significativas para esta validación estadística',
+ // 23.StatisticalValidationResultKaplanMeier.tsx
+ 'kaplanMeier.axis.time': 'Tiempo',
+ 'kaplanMeier.axis.probability': 'Probabilidad',
+ 'kaplanMeier.info.coxRegression': 'Estas métricas se calculan usando Cox-Regression',
+ 'kaplanMeier.header.clusteringMetrics': 'Métricas de clustering',
+ 'kaplanMeier.button.clusteringModel': 'Modelo de clustering',
+ 'kaplanMeier.button.groupByClinical': 'Agrupar por atributo clínico',
+ 'kaplanMeier.select.clinicalAttribute': 'Atributo clínico para agrupar',
+ 'kaplanMeier.metric.cIndex': 'Índice C',
+ 'kaplanMeier.metric.partialLogLikelihood': 'Log-verosimilitud parcial',
+ 'kaplanMeier.button.seeSamplesAndClusters': 'Ver muestras y clusters',
+ 'kaplanMeier.modal.samplesAndClusters': 'Muestras y clusters',
+ // 24.StatisticalValidationResultMetrics.tsx
+ 'statValidationMetrics.header.metrics': 'métricas',
+ 'statValidationMetrics.header.validationMetrics': 'Métricas de validación',
+ 'statValidationMetrics.metric.mse': 'MSE',
+ 'statValidationMetrics.metric.r2Score': 'Puntaje R2',
+ 'statValidationMetrics.header.model': 'Modelo',
+ // 25.NewStatisticalValidationModal.tsx
+ 'newStatValidation.header.create': 'Crear nueva validación estadística',
+ 'newStatValidation.step.trainedModel': 'Paso 1: Modelo entrenado',
+ 'newStatValidation.step.validationDatasets': 'Paso 2: Conjuntos de validación',
+ // 26.StatisticalValidationMenu.tsx
+ 'statValidationMenu.bestFeatures': 'Características más significativas',
+ 'statValidationMenu.bestFeatures.info': 'Características más significativas para el análisis de supervivencia',
+ 'statValidationMenu.kaplanMeier.info': 'Curva mostrando supervivencia o hazard ratio',
+ 'statValidationMenu.heatmap': 'Mapa de calor',
+ 'statValidationMenu.heatmap.info': 'Mapa de calor para cada muestra y molécula',
+ // 27.StatisticalValidationsTable.tsx
+ 'statValidationsTable.stopValidation.header': 'Detener validación estadística',
+ 'statValidationsTable.stopValidation.confirm': '¿Está seguro de que desea detener la validación estadística {name}?',
+ 'statValidationsTable.deleteValidation.header': 'Eliminar validación estadística',
+ 'statValidationsTable.deleteValidation.confirm': '¿Está seguro de que desea eliminar la validación estadística {name}?',
+ 'statValidationsTable.headerTitle': 'Validaciones estadísticas',
+ 'statValidationsTable.headers.model': 'Modelo',
+ 'statValidationsTable.headers.datasets': 'Conjuntos de datos',
+ 'statValidationsTable.headers.actions': 'Acciones',
+ 'statValidationsTable.newValidation': 'Nueva validación estadística',
+ 'statValidationsTable.actions.seeResults': 'Ver resultados',
+ 'statValidationsTable.actions.stopValidation': 'Detener validación estadística',
+ 'statValidationsTable.actions.deleteValidation': 'Eliminar validación estadística',
+ // 28.NewClusteringModelForm.tsx
+ 'newClusteringForm.placeholder.algorithm': 'Seleccione un algoritmo',
+ 'newClusteringForm.label.searchOptimalClusters': 'Buscar el número óptimo de clusters',
+ 'newClusteringForm.info.nClusters': 'Número de clusters para agrupar los datos. El número óptimo puede encontrarse buscando el codo en la curva de la suma de distancias cuadradas entre muestras y su centro de cluster más cercano.',
+ 'newClusteringForm.placeholder.metric': 'Seleccione una métrica',
+ 'newClusteringForm.placeholder.scoringMethod': 'Seleccione un método',
+ 'newClusteringForm.info.algorithm': 'K-Means: agrupa datos minimizando la varianza intra-cluster; útil para RNA y miRNA. Spectral Clustering: usa similitud basada en grafos para patrones complejos; ideal para metilación y CNA. BK-Means: variación jerárquica de K-Means, adecuada para datasets clínicos y multi-ómicos. Método de Ward: minimiza la varianza en clustering jerárquico; útil para combinar RNA y metilación.',
+ 'newClusteringForm.info.metric': 'Cox Regression: modelo de riesgos proporcionales para asociaciones entre multi-ómicos y resultados clínicos. Log-Rank Test: prueba no paramétrica para comparar distribuciones de supervivencia; actualmente no disponible.',
+ 'newClusteringForm.info.scoringMethod': 'C-Index: medida de concordancia entre resultados predichos y observados; valores altos indican mejor desempeño. Log Likelihood: probabilidad de observar los datos dado el modelo; valores bajos indican mejor desempeño.',
+ 'newClusteringForm.info.randomState': 'Semilla usada por el generador aleatorio para asegurar reproducibilidad.',
+ 'newClusteringForm.info.penalizer': 'Útil cuando hay pocas muestras o eventos observados; aumenta la robustez del modelo evitando problemas con valores NaN.',
+ // 29.NewRFModelForm.tsx
+ 'newRFForm.label.searchOptimalTrees': 'Buscar el número óptimo de árboles',
+ 'newRFForm.info.searchOptimalTrees': 'Esta opción es útil cuando el número de muestras en los datos clínicos es pequeño o hay pocos eventos observados; establecer este valor aumenta la robustez del modelo en tales casos, evitando problemas con valores NaN.',
+ 'newRFForm.label.maxDepth': 'Profundidad máxima',
+ 'newRFForm.info.maxDepth': 'La profundidad máxima del árbol',
+ 'newRFForm.info.randomState': 'Semilla utilizada por el generador de números aleatorios',
+ 'newRFForm.label.nEstimators': 'Número de árboles',
+ 'newRFForm.info.nEstimators': 'El número de árboles (estimadores) utilizados en el modelo Random Forest.',
+ // 30.NewSVMModelForm.tsx
+ 'newSVMForm.info.kernel.linear': 'Kernel lineal: Mejor para datos linealmente separables; comúnmente usado para clasificación simple de características genómicas o clínicas.',
+ 'newSVMForm.info.kernel.polynomial': 'Kernel polinomial: Captura patrones no lineales; efectivo para relaciones complejas en datos multi-ómicos.',
+ 'newSVMForm.info.kernel.rbf': 'Kernel RBF: Mapea los datos a un espacio de mayor dimensión; ideal para manejar separaciones no lineales en análisis de ARN y metilación.',
+ 'newSVMForm.placeholder.kernel': 'Seleccionar un kernel',
+ 'newSVMForm.label.maxIterations': 'Iteraciones máximas',
+ 'newSVMForm.info.maxIterations': 'El número máximo de iteraciones a ejecutar',
+ 'newSVMForm.info.randomState': 'Semilla utilizada por el generador de números aleatorios',
+ // 31.NewTrainedModelModal
+ 'newTrainedModelModal.header.create': 'Crear nuevo modelo entrenado',
+
+ 'newTrainedModelModal.step1.trainingParameters': 'Paso 1: Parámetros de entrenamiento',
+ 'newTrainedModelModal.step2.trainingDatasets': 'Paso 2: Conjuntos de datos de entrenamiento',
+
+ 'newTrainedModelModal.header.selectModel': 'Seleccionar un nuevo modelo para entrenar',
+ 'newTrainedModelModal.placeholder.selectModel': 'Seleccionar un modelo',
+ 'newTrainedModelModal.header.selectModelParameters': 'Seleccionar parámetros del modelo',
+ 'newTrainedModelModal.header.selectCVParameters': 'Seleccionar parámetros de validación cruzada',
+ 'newTrainedModelModal.info.numberOfFolds': 'Define el número de divisiones de datos para la validación cruzada; asegura una evaluación robusta del modelo y previene el sobreajuste.',
+ // 32.BiomarkerTrainedModelsTable
+ 'biomarkerTrainedModelsTable.header.stopTraining': 'Detener entrenamiento',
+ 'biomarkerTrainedModelsTable.confirm.stopTraining': '¿Está seguro de que desea detener el entrenamiento del modelo {modelName}?',
+ 'biomarkerTrainedModelsTable.button.stop': 'Detener',
+ 'biomarkerTrainedModelsTable.header.deleteBiomarker': 'Eliminar biomarcador',
+ 'biomarkerTrainedModelsTable.confirm.deleteBiomarker': '¿Está seguro de que desea eliminar el biomarcador {modelName}?',
+ 'biomarkerTrainedModelsTable.header.trainedModels': 'Modelos entrenados',
+ 'biomarkerTrainedModelsTable.header.model': 'Modelo',
+ 'biomarkerTrainedModelsTable.header.bestCVMetric': 'Mejor métrica de validación cruzada',
+ 'biomarkerTrainedModelsTable.header.datasets': 'Conjuntos de datos',
+ 'biomarkerTrainedModelsTable.header.actions': 'Acciones',
+ 'biomarkerTrainedModelsTable.filter.modelType': 'Tipo de modelo',
+ 'biomarkerTrainedModelsTable.button.newTrainedModel': 'Nuevo modelo entrenado',
+ 'biomarkerTrainedModelsTable.search.placeholder': 'Buscar por nombre o descripción',
+ 'biomarkerTrainedModelsTable.button.stopTrainedModel': 'Detener modelo entrenado',
+ 'biomarkerTrainedModelsTable.button.deleteTrainedModel': 'Eliminar modelo entrenado',
+ 'biomarkerTrainedModelsTable.button.deleteTrainedModelNotAllowed': 'El modelo entrenado no puede eliminarse porque tiene validaciones estadísticas y/o experimentos de inferencia relacionados',
+ // 33.ModelDetailsPanels
+ 'modelDetails.general.bestFitnessValue': 'Mejor valor de fitness:',
+ 'modelDetails.svm.task': 'Tarea:',
+ 'modelDetails.rf.numberOfEstimators': 'Número de estimadores:',
+ 'modelDetails.rf.maxDepth': 'Profundidad máxima:',
+ // 34.BiomarkerStateLabel
+ 'biomarkerState.completed': 'El experimento está completo',
+ 'biomarkerState.finishedWithError': 'El experimento terminó con errores. Intenta nuevamente',
+ 'biomarkerState.waitingForQueue': 'El proceso de este experimento comenzará pronto',
+ 'biomarkerState.noSamplesInCommon': 'Los datasets no tienen muestras en común',
+ 'biomarkerState.inProcess': 'El experimento está siendo procesado',
+ 'biomarkerState.stopping': 'El experimento está siendo detenido',
+ 'biomarkerState.stopped': 'El experimento fue detenido',
+ 'biomarkerState.reachedAttemptsLimit': 'El experimento falló varias veces. Cambia algunos parámetros e intenta nuevamente',
+ 'biomarkerState.noFeaturesFound': 'No se encontraron features. Cambia algunos parámetros e intenta nuevamente',
+ 'biomarkerState.emptyDataset': 'Después de filtrar valores inválidos como NaN o inf, no quedaron moléculas ni muestras para hacer la inferencia. Quizás las moléculas solicitadas no existen en el dataset, o todos los pacientes contienen datos NaN o inf. Cambia el dataset usado o corrige tus datos e intenta nuevamente.',
+ 'biomarkerState.noValidMolecules': 'El dataset usado no tiene suficientes moléculas para calcular el experimento (por ejemplo, tiene moléculas diferentes a las especificadas en el Biomarker). Selecciona otro dataset e intenta nuevamente',
+ 'biomarkerState.numberOfSamplesFewerThanCvFolds': 'Hay menos miembros en cada clase que el número de folds de CrossValidation. Se intentó usar un número menor de splits pero aún así falló. Selecciona un dataset más grande e intenta nuevamente',
+ 'biomarkerState.timeoutExceeded': 'El análisis alcanzó el límite de tiempo. Cambia algunos parámetros e intenta nuevamente',
+ // 35.SVMKernelTask
+ 'svmTask.regression': 'Regresión',
+ 'svmTask.ranking': 'Clasificación',
+ // 36.TrainedModelStateLabel
+ 'trainedModelState.completed': 'El experimento está completo{cvModified, select, true { (el número de folds de CrossValidation fue modificado para ser estratificado)} false {}}',
+ 'trainedModelState.finishedWithError': 'El experimento terminó con errores. Intenta nuevamente',
+ 'trainedModelState.waitingForQueue': 'El proceso de este experimento comenzará pronto',
+ 'trainedModelState.noSamplesInCommon': 'Los datasets no tienen muestras en común',
+ 'trainedModelState.inProcess': 'El experimento está siendo procesado',
+ 'trainedModelState.stopping': 'El experimento está siendo detenido',
+ 'trainedModelState.stopped': 'El experimento fue detenido',
+ 'trainedModelState.reachedAttemptsLimit': 'El experimento falló varias veces. Cambia algunos parámetros e intenta nuevamente',
+ 'trainedModelState.noFeaturesFound': 'No se encontraron features. Cambia algunos parámetros e intenta nuevamente',
+ 'trainedModelState.noBestModelFound': 'No se pudo obtener un modelo. Quizás hay menos muestras que el número de folds en la CrossValidation o los datos presentan alta colinealidad. Cambia algunos parámetros como el penalizador o el número de folds en el proceso de CV e intenta nuevamente',
+ 'trainedModelState.numberOfSamplesFewerThanCvFolds': 'Hay menos miembros en cada clase que el número de folds de CrossValidation. Se intentó usar un número menor de splits pero aún así falló. Selecciona un dataset más grande e intenta nuevamente',
+ 'trainedModelState.modelDumpNotAvailable': 'El proceso de selección de features terminó correctamente, pero hubo un problema al obtener el modelo. Intenta entrenar un nuevo modelo',
+ 'trainedModelState.timeoutExceeded': 'El proceso de entrenamiento alcanzó el límite de tiempo. Cambia algunos parámetros e intenta nuevamente',
+ 'trainedModelState.emptyDataset': 'Después de filtrar valores inválidos como NaN o inf, no quedaron moléculas ni muestras para entrenar el modelo. Quizás las moléculas solicitadas no existen en el dataset, o todos los pacientes contienen datos NaN o inf',
+ // 37.BiomarkerTypeSelection
+ 'biomarkerType.createNew': 'Crear un nuevo Biomarker',
+ 'biomarkerType.chooseType': 'Elegir tipo de Biomarker',
+ 'biomarkerType.empty.title': 'Vacío',
+ 'biomarkerType.empty.description': 'Crear un Biomarker vacío. Luego puedes añadir moléculas o features (genes, microRNAs, metilación de ADN, CNAs) que compondrán el biomarker',
+ 'biomarkerType.featureSelection.title': 'Selección de features/ML',
+ 'biomarkerType.featureSelection.description': 'Como punto de partida, puedes seleccionar un Biomarker previamente descubierto, un Biomarker reconocido, o un conjunto de genes que quieras probar. Este método seleccionará el subconjunto molecular que mejor se ajuste a la predicción',
+ // 38.BBHAAdvanced
+ 'bbha.numberOfStars': 'Número de estrellas',
+ 'bbha.numberOfStars.info': 'Número de estrellas en el Binary Black Hole Algorithm. Cada una de estas estrellas evalúa un subconjunto diferente de features. Aumentar este número incrementa las chances de evaluar el subconjunto más óptimo pero retrasa más el resultado del experimento',
+ 'bbha.numberOfIterations.info': 'Número de iteraciones en el Binary Black Hole Algorithm. En cada iteración se calcula la función de fitness para cada estrella con su correspondiente subconjunto de features. Aumentar este número permite evaluar más combinaciones de features pero retrasa más el resultado del experimento',
+ 'bbha.version': 'Versión de BBHA',
+ 'bbha.version.original': 'El enfoque Original ejecuta el Binary Black Hole Algorithm tal como se definió en',
+ 'bbha.version.v2': 'La Versión 2 es una versión mejorada definida en este',
+ 'bbha.coefficientExplanation': 'Coeficiente especificado en el',
+ 'bbha.useSpark': 'Intentar optimizar usando Apache Spark',
+ 'bbha.useSpark.info': 'Si esta opción está habilitada, el experimento se ejecutará (si es posible) usando Apache Spark para optimizar los tiempos de ejecución',
+ // 39.CoxRegressionAdvanced
+ 'coxRegression.keepTopN': 'Mantener los N principales',
+ 'coxRegression.keepTopN.info': 'Número máximo de features que se conservarán después del procesamiento. Las features se ordenan en orden descendente según sus coeficientes, manteniendo primero las más significativas. Si este valor se deja vacío, se conservarán todas aquellas cuyos coeficientes sean distintos de 0',
+ // 40.GAAdvanced
+ 'ga.populationSize': 'Tamaño de la población',
+ 'ga.populationSize.info': 'Número de soluciones candidatas (individuos o posibles soluciones) que coexisten en cada generación del Genetic Algorithm. Aumentar este número permite evaluar más combinaciones de features pero retrasa más el resultado del experimento',
+ 'ga.mutationRate': 'Tasa de mutación',
+ 'ga.floatPlaceholder': 'Un número decimal',
+ 'ga.mutationRate.info': 'Determina la probabilidad de que un bit (dígito binario) en una solución candidata sea alterado o cambiado aleatoriamente durante el proceso de evolución. Esta opción introduce pequeños cambios aleatorios para explorar nuevas posibilidades.',
+ 'ga.numberOfIterations.info': 'Número de iteraciones en el Genetic Algorithm. En cada iteración se calcula la función de fitness para cada solución candidata con su correspondiente subconjunto de features. Aumentar este número permite evaluar más combinaciones de features pero retrasa más el resultado del experimento',
+ 'ga.useSpark': 'Intentar optimizar usando Apache Spark',
+ 'ga.useSpark.info': 'Si esta opción está habilitada, el experimento se ejecutará (si es posible) usando',
+ // 41.ClusteringPanel
+ 'clustering.algorithm.placeholder': 'Algoritmo de Clustering',
+ // 42.RFPanel
+ 'rf.numberOfEstimators': 'Número de estimadores',
+ 'rf.maxDepth': 'Profundidad máxima',
+ // 43.SVMPanel
+ 'svm.kernel.placeholder': 'Seleccionar un Kernel',
+ // 44.FeatureSelectionForm
+ 'featureSelection.fitnessFunction': 'Función de fitness',
+ 'featureSelection.searchOptimalClusters': 'Buscar el número óptimo de clusters (próximamente)',
+ 'featureSelection.maxIterations': 'Máximo de iteraciones',
+ // 45.FeatureSelectionStep1
+ 'featureSelectionStep1.headerTitle': 'Biomarcadores',
+ 'featureSelectionStep1.searchPlaceholder': 'Buscar por nombre',
+ // 46.FeatureSelectionStep3
+ 'featureSelectionStep3.blindSearch': 'Búsqueda exhaustiva',
+ 'featureSelectionStep3.expertMode': 'Modo experto',
+ 'featureSelectionStep3.geneticAlgorithms': 'Algoritmos genéticos',
+ // 47.CrossValidationInput
+ 'crossValidation.integerPlaceholder': 'Un número entero',
+ // 48.FeatureSelectionPanel
+ 'featureSelectionPanel.tag': 'Etiqueta',
+ 'featureSelectionPanel.step1': 'Paso 1',
+ 'featureSelectionPanel.step2': 'Paso 2: Conjuntos de datos',
+ 'featureSelectionPanel.step3': 'Paso 3: Selección de características',
+ 'featureSelectionPanel.selectBiomarker': 'Seleccionar biomarcador',
+ 'featureSelectionPanel.selectedBiomarker': 'Seleccionado {biomarker}',
+ // 50.NewBiomarkerForm
+ 'newBiomarkerForm.newBiomarker': 'Nuevo biomarcador',
+ 'newBiomarkerForm.cannotEditMolecules': 'No se pueden editar las moléculas',
+ 'newBiomarkerForm.cannotEditMoleculesDescription': 'Este biomarcador contiene modelos y validaciones asociadas, por lo que sus moléculas no pueden modificarse. Para cambiar sus moléculas, considere clonar este biomarcador y trabajar con su copia.',
+ 'newBiomarkerForm.selectMolecule': 'Seleccionar molécula',
+ 'newBiomarkerForm.invalidMoleculesWarning': 'Algunas moléculas (en naranja) de los paneles no fueron encontradas en nuestra base de datos.',
+ 'newBiomarkerForm.ambiguousMoleculesWarning': 'Hay moléculas ambiguas (en amarillo). Por favor seleccione las apropiadas en los paneles.',
+ 'newBiomarkerForm.ignoreMoleculesWarnings': 'Ignorar moléculas con advertencias',
+ 'newBiomarkerForm.ignoreMoleculesInfo': 'Este mensaje no indica un error en sus datos, sino que estas moléculas no fueron encontradas durante la validación. Esto puede deberse a datos desactualizados o diferentes nomenclaturas. Si está seguro de que no hay correcciones por realizar y desea continuar guardando el biomarcador, marque la casilla para habilitar el envío.',
+ 'newBiomarkerForm.sendForm': 'Enviar formulario',
+ 'newBiomarkerForm.resetForm': 'Reiniciar formulario',
+ 'newBiomarkerForm.resetFormDescription': 'Va a reiniciar el formulario y limpiar todos los datos ingresados.',
+
+ // 51.SelectDropDownSingleMolecule
+ 'selectDropDownSingleMolecule.selectMolecules': 'Seleccionar moléculas',
+ 'selectDropDownSingleMolecule.noResults': 'Molécula no encontrada',
+ 'selectDropDownSingleMolecule.ignoreAlias': 'No usar alias propuesto',
+ 'selectDropDownSingleMolecule.ignoreAliasInfo': 'Si está marcado, la molécula será agregada al biomarcador con el nombre encontrado en la consulta.',
+ 'selectDropDownSingleMolecule.searchInfo': 'Este motor de búsqueda mostrará moléculas que comiencen con el criterio de búsqueda y, si es necesario, el alias validado encontrado en nuestra base de datos. Este último será agregado al biomarcador. Si desea ingresar la molécula tal como fue encontrada, marque la casilla inferior.',
+
+ // 52.TextAreaMolecules
+ 'textAreaMolecules.insertMolecules': 'Insertar moléculas',
+
+ // 53.BiomarkerDetailsMenu
+ 'biomarkerDetailsMenu.moleculesDetails': 'Detalles de moléculas',
+ 'biomarkerDetailsMenu.moleculesDetailsInfo': 'Detalles de las moléculas que componen el biomarcador',
+ 'biomarkerDetailsMenu.trainedModels': 'Modelos entrenados',
+ 'biomarkerDetailsMenu.trainedModelsInfo': 'Panel para listar y entrenar modelos de Machine Learning a partir de información genómica y epigenómica. Estos modelos permiten validación estadística del poder pronóstico/predictivo del biomarcador o inferencia sobre nuevos datos.',
+ 'biomarkerDetailsMenu.statisticalValidations': 'Validaciones estadísticas',
+ 'biomarkerDetailsMenu.statisticalValidationsInfo': 'Realizar validaciones estadísticas a partir de modelos de Machine Learning previamente entrenados.',
+ 'biomarkerDetailsMenu.inference': 'Inferencia',
+ 'biomarkerDetailsMenu.inferenceInfo': 'Realizar inferencia sobre nuevos datos genómicos y epigenómicos a partir de modelos de Machine Learning previamente entrenados.',
+ 'biomarkerDetailsMenu.featureSelectionSummary': 'Resumen de selección de características',
+ 'biomarkerDetailsMenu.featureSelectionSummaryInfo': 'Detalles del proceso de selección de características.',
+
+ // 54.BiomarkerOriginLabel
+ 'biomarkerOriginLabel.manual': 'Manual',
+ 'biomarkerOriginLabel.featureSelection': 'Selección de características',
+
+ // 55.SharedInstitutionsBiomarker.tsx
+ 'sharedInstitutionsBiomarker.header': 'Instituciones compartidas',
+ 'sharedInstitutionsBiomarker.selectPlaceholder': 'Seleccione una institución para compartir',
+ 'sharedInstitutionsBiomarker.addInstitution': 'Agregar institución',
+ 'sharedInstitutionsBiomarker.removeInstitution': 'Eliminar institución',
+ 'sharedInstitutionsBiomarker.confirm.share.header': 'Compartir biomarcador',
+ 'sharedInstitutionsBiomarker.confirm.share.content': '¿Está seguro de que desea compartir este biomarcador con la institución seleccionada?',
+ 'sharedInstitutionsBiomarker.confirm.stopShare.header': 'Dejar de compartir con institución',
+ 'sharedInstitutionsBiomarker.confirm.stopShare.content': '¿Está seguro de que desea dejar de compartir este biomarcador con esta institución?',
+ 'sharedInstitutionsBiomarker.users.title': 'Usuarios de {institutionName}',
+ 'sharedInstitutionsBiomarker.users.column': 'Nombre de usuario',
+ 'sharedInstitutionsBiomarker.users.searchPlaceholder': 'Buscar por nombre de usuario',
+
+ // 56.SharedUsersBiomarker.tsx
+ 'sharedUsersBiomarker.header': 'Usuarios compartidos',
+ 'sharedUsersBiomarker.selectPlaceholder': 'Seleccione un usuario para compartir',
+ 'sharedUsersBiomarker.addUser': 'Agregar usuario',
+ 'sharedUsersBiomarker.removeUser': 'Eliminar usuario',
+ 'sharedUsersBiomarker.confirm.share.header': 'Compartir biomarcador',
+ 'sharedUsersBiomarker.confirm.share.content': '¿Está seguro de que desea compartir este biomarcador con el usuario seleccionado?',
+ 'sharedUsersBiomarker.confirm.stopShare.header': 'Dejar de compartir con usuario',
+ 'sharedUsersBiomarker.confirm.stopShare.content': '¿Está seguro de que desea dejar de compartir este biomarcador con este usuario?',
+
+ // 58.NewCGDSDatasetForm
+ 'cgdsDatasetForm.filePath.placeholder': 'Ruta del archivo',
+ 'cgdsDatasetForm.separator.placeholder': 'Seleccionar separador',
+ 'cgdsDatasetForm.separator.label': 'Separador',
+ 'cgdsDatasetForm.separator.comma': 'Coma',
+ 'cgdsDatasetForm.separator.semicolon': 'Punto y coma',
+ 'cgdsDatasetForm.separator.tab': 'Tabulación',
+ 'cgdsDatasetForm.separator.colon': 'Dos puntos',
+ 'cgdsDatasetForm.separator.whitespace': 'Espacio en blanco',
+ 'cgdsDatasetForm.observation.placeholder': 'Observación',
+ 'cgdsDatasetForm.headerIndex.placeholder': 'Índice de fila del encabezado (indexado desde 0)',
+ 'cgdsDatasetForm.headerIndex.help': 'Los índices de fila comienzan desde 0',
+ 'cgdsDatasetForm.mongoName.placeholder': 'Nombre de la colección de Mongo',
+ 'cgdsDatasetForm.icon.add': 'Agregar dataset',
+ 'cgdsDatasetForm.icon.remove': 'Eliminar dataset',
+
+ // 59.NewCGDSStudyForm
+ 'cgdsStudyForm.header': 'Agregar especificación del estudio CGDS',
+ 'cgdsStudyForm.url.placeholder': 'URL (tar.gz/zip)',
+ 'cgdsStudyForm.urlInfo.placeholder': 'URL de información extra',
+ 'cgdsStudyForm.datasets.header': 'Datasets CGDS',
+ 'cgdsStudyForm.dataset.methylation': 'Metilación',
+ 'cgdsStudyForm.dataset.clinicalPatients': 'Pacientes clínicos',
+ 'cgdsStudyForm.dataset.clinicalSamples': 'Muestras clínicas',
+ 'cgdsStudyForm.requiredField': 'Campo requerido',
+ 'cgdsStudyForm.syncWarning': 'Para tener los datos disponibles, debe realizar la sincronización al menos una vez',
+ 'cgdsStudyForm.addStudy': 'Agregar estudio',
+ 'cgdsStudyForm.editStudy': 'Editar estudio',
+
+ // 60.BoxplotsCommons
+ 'boxPlotTooltip.min': 'Mínimo',
+ 'boxPlotTooltip.firstQuartile': 'Primer cuartil',
+ 'boxPlotTooltip.median': 'Mediana',
+ 'boxPlotTooltip.thirdQuartile': 'Tercer cuartil',
+ 'boxPlotTooltip.max': 'Máximo',
+ 'boxPlotTooltip.mean': 'Media',
+ 'boxPlotTooltip.outliers': 'Valores atípicos (usando MAD)',
+
+ // 61.ClusterLabelsSetsModal
+ 'clusterLabelsSetsModal.header': 'Conjuntos de etiquetas de clúster',
+ 'clusterLabelsSetsModal.newClusterModel': 'Nuevo modelo de clúster',
+ 'clusterLabelsSetsModal.searchPlaceholder': 'Buscar por nombre o descripción',
+
+ // 62.NewClusterLabelsSetModal
+ 'newClusterLabelsSetModal.header': 'Nuevo conjunto de etiquetas de clúster',
+ 'newClusterLabelsSetModal.labelsHeader': 'Etiquetas',
+ 'newClusterLabelsSetModal.clusterId': 'ID del clúster',
+ 'newClusterLabelsSetModal.label': 'Etiqueta',
+ 'newClusterLabelsSetModal.addLabel': 'Agregar etiqueta',
+ 'newClusterLabelsSetModal.deleteLabel': 'Eliminar etiqueta',
+ 'newClusterLabelsSetModal.color': 'Color',
+
+ // 63.NewPredictionRangeLabelsSetModal
+ 'newPredictionRangeLabelsSetModal.header': 'Nuevos conjuntos de etiquetas de rango de predicción',
+ 'newPredictionRangeLabelsSetModal.subHeader': 'Nuevo PredictionRangeLabelsSet',
+ 'newPredictionRangeLabelsSetModal.labelsHeader': 'Etiquetas',
+ 'newPredictionRangeLabelsSetModal.minValue': 'Valor mínimo',
+ 'newPredictionRangeLabelsSetModal.maxValue': 'Valor máximo',
+ 'newPredictionRangeLabelsSetModal.label': 'Etiqueta',
+ 'newPredictionRangeLabelsSetModal.deleteLabel': 'Eliminar etiqueta',
+ 'newPredictionRangeLabelsSetModal.addLabel': 'Agregar etiqueta',
+ 'newPredictionRangeLabelsSetModal.color': 'Color',
+ 'newPredictionRangeLabelsSetModal.error.maxValue': 'El valor máximo debe ser mayor que el valor mínimo',
+ 'newPredictionRangeLabelsSetModal.error.overlap': 'Los rangos se superponen con la etiqueta "{label}" (posición {position})',
+
+ // 64.PredictionRangeLabelsSetModal
+ 'predictionRangeLabelsSetModal.header': 'Conjuntos de etiquetas de rango de predicción',
+ 'predictionRangeLabelsSetModal.newModel': 'Nuevo conjunto de etiquetas de rango de predicción',
+ 'predictionRangeLabelsSetModal.searchPlaceholder': 'Buscar por nombre o descripción',
+
+ // 65.PredictionRangeLabelsSetSelect
+ 'predictionRangeLabelsSetSelect.label': 'Usar una etiqueta de rango',
+ 'predictionRangeLabelsSetSelect.placeholder': 'Usar etiquetas de rango',
+
+ // 66.EditIcon.tsx
+ 'common.edit': 'Editar',
+
+ // 67.PaginatedTable.tsx
+ 'paginatedTable.loading': 'Cargando...',
+ 'paginatedTable.searchLabel': 'Nombre/Descripción',
+ 'paginatedTable.entries': 'Entradas',
+
+ // 68.SourceSelectors.tsx
+ 'sourceSelectors.clinicalProfile': 'Perfil clínico',
+ 'sourceSelectors.mRNAProfile': 'Perfil mRNA',
+ 'sourceSelectors.mirnaProfile': 'Perfil miRNA',
+ 'sourceSelectors.cnaProfile': 'Perfil CNA',
+ 'sourceSelectors.methylationProfile': 'Perfil de metilación',
+
+ // 69.SwitchPublicButton.tsx
+ 'switchPublicButton.makePrivate': 'Hacer privado {nameEntity}',
+ 'switchPublicButton.makePublic': 'Hacer público {nameEntity}',
+ 'switchPublicButton.confirmMakePrivate': '¿Está seguro de hacer privado {nameEntity}?',
+ 'switchPublicButton.confirmMakePublic': '¿Está seguro de hacer público {nameEntity}?',
+
+ // 70.TableCellSources.tsx
+ 'tableCellSources.downloadClinical': 'Descargar archivo clínico fuente',
+ 'tableCellSources.downloadMrna': 'Descargar archivo fuente mRNA',
+ 'tableCellSources.downloadMirna': 'Descargar archivo fuente miRNA',
+ 'tableCellSources.downloadCna': 'Descargar archivo fuente CNA',
+ 'tableCellSources.downloadMethylation': 'Descargar archivo fuente de metilación',
+
+ // 71.TagForm.tsx
+ 'tagForm.newTag': 'Nueva etiqueta',
+
+ // 72.TagLabel.tsx
+ 'tagLabel.noTagAssigned': 'Sin etiqueta asignada',
+
+ // 73.TryAgainSegment.tsx
+ 'tryAgainSegment.message': 'Algo salió mal, por favor inténtelo nuevamente',
+ 'tryAgainSegment.button': 'Intentar nuevamente',
+
+ // 74.DifferentialExpressionForm.tsx
+ 'differentialExpressionForm.header': 'Nueva Expresión Diferencial',
+ 'differentialExpressionForm.samplesMRNA': 'Muestras mRNA: {count}',
+ 'differentialExpressionForm.samplesClinical': 'Muestras clínicas: {count}',
+ 'differentialExpressionForm.samplesInCommon': 'Muestras en común: {count}',
+ 'differentialExpressionForm.thresholdPercentile': 'Percentil umbral: {value}',
+ 'differentialExpressionForm.thresholdPercentile.info': 'Umbral percentil para filtrar genes de baja expresión (por defecto 0.15)',
+ 'differentialExpressionForm.thresholdStd': 'Desviación estándar umbral: {value}',
+ 'differentialExpressionForm.thresholdStd.info': 'Umbral de varianza para filtrado de genes (por defecto 1e-4)',
+ 'differentialExpressionForm.top': 'Top: {value}',
+ 'differentialExpressionForm.top.info': 'Cantidad más significativa de genes a conservar como resultado',
+ 'differentialExpressionForm.editExperiment': 'Editar experimento',
+ 'differentialExpressionForm.createExperiment': 'Crear experimento',
+ 'differentialExpressionForm.cancelEdit': 'Cancelar edición',
+ 'differentialExpressionForm.resetForm': 'Reiniciar formulario',
+ 'differentialExpressionForm.successCreated': '¡Experimento de Expresión Diferencial creado exitosamente!',
+ 'differentialExpressionForm.successUpdated': '¡Experimento de Expresión Diferencial actualizado exitosamente!',
+ 'differentialExpressionForm.errorCreating': '¡Error al crear el experimento de Expresión Diferencial!',
+ 'differentialExpressionForm.errorUpdating': '¡Error al actualizar el experimento de Expresión Diferencial!',
+
+ // 75.DifferentialExpressionInputClinicalAttribute.tsx
+ 'differentialExpressionInputClinicalAttribute.label': 'Agrupar por atributo clínico',
+ 'differentialExpressionInputClinicalAttribute.placeholder': 'Atributo clínico para agrupar',
+
+ // 76.DifferentialExpressionModalResults.tsx
+ 'differentialExpressionModalResults.header': 'Resultados del Análisis de Expresión Diferencial - {name}',
+ 'differentialExpressionModalResults.tab.volcanoPlot': 'Gráfico volcán',
+
+ // 77.DifferentialExpressionModalResultsTableView.tsx
+ 'diffExpResultsTable.logFoldThreshold': 'Umbral de Log Fold',
+ 'diffExpResultsTable.headerTitle': 'Resultados de Expresión Diferencial',
+ 'diffExpResultsTable.noLogFold': 'Sin filtro de Log Fold',
+ 'diffExpResultsTable.pValueThreshold': 'Umbral de p-value',
+ 'diffExpResultsTable.noPValue': 'Sin filtro de p-value',
+ 'diffExpResultsTable.gene': 'Gen',
+ 'diffExpResultsTable.adjPValue': 'p-value ajustado',
+ 'diffExpResultsTable.avgExpression': 'Expresión promedio',
+ 'diffExpResultsTable.bStatistic': 'Estadístico B',
+ 'diffExpResultsTable.logFoldChange': 'Cambio Log Fold',
+ 'diffExpResultsTable.pValue': 'p-value',
+ 'diffExpResultsTable.tStatistic': 'Estadístico t',
+ 'diffExpResultsTable.downloadCSV': 'Descargar resultados en un archivo CSV',
+ 'diffExpResultsTable.searchPlaceholder': 'Buscar por gen',
+
+ // 78.DifferentialExpressionModalResultsVolcanoPlot
+ 'differentialExpression.volcanoPlot.title': 'Gráfico volcán',
+ 'differentialExpression.volcanoPlot.fcThreshold': 'Umbral |log2FC|',
+ 'differentialExpression.volcanoPlot.pValueThreshold': 'Umbral de p-value',
+ 'differentialExpression.volcanoPlot.showThresholds': 'Mostrar umbrales',
+
+ // 79.DifferentialExpressionPanel
+ 'differentialExpression.panel.noMethod': 'Sin método',
+ 'differentialExpression.panel.selectMethod': 'Seleccionar un método existente',
+ 'differentialExpression.panel.method': 'Método',
+ 'differentialExpression.panel.headerTitle': 'Análisis de Expresión Diferencial',
+ 'differentialExpression.panel.nameDescription': 'Nombre/Descripción',
+ 'differentialExpression.panel.searchByNameDescription': 'Buscar por nombre/descripción',
+ 'differentialExpression.panel.stopSuccess': '¡Experimento de Expresión Diferencial detenido exitosamente!',
+ 'differentialExpression.panel.stopError': '¡Error al detener el experimento de Expresión Diferencial!',
+ 'differentialExpression.panel.deleteSuccess': '¡Experimento de Expresión Diferencial eliminado exitosamente!',
+ 'differentialExpression.panel.deleteError': '¡Error al eliminar el experimento de Expresión Diferencial!',
+ 'differentialExpression.panel.downloadMrnaSource': 'Descargar archivo fuente mRNA',
+ 'differentialExpression.panel.downloadClinicalSource': 'Descargar archivo clínico fuente',
+ 'differentialExpression.panel.publicVisible': 'Todos los usuarios de la plataforma pueden ver este experimento',
+ 'differentialExpression.panel.publicHidden': 'Si esto está marcado, todos los usuarios de la plataforma pueden ver (pero no editar ni eliminar) este elemento',
+ 'differentialExpression.panel.seeResults': 'Ver resultados',
+ 'differentialExpression.panel.stopExperiment': 'Detener experimento',
+ 'differentialExpression.panel.stopExperimentTitle': 'Detener experimento',
+ 'differentialExpression.panel.stopExperimentConfirm': '¿Está seguro de detener el experimento?',
+ 'differentialExpression.panel.deleteExperiment': 'Eliminar experimento',
+ // 80.Volcano Plot
+ 'differentialExpression.volcanoPlot.significant': 'Significativo',
+ 'differentialExpression.volcanoPlot.notSignificant': 'No significativo',
+ 'differentialExpression.volcanoPlot.logFoldChange': 'log2(Cambio de expresión)',
+ 'differentialExpression.volcanoPlot.logPValue': '-log10(p-value)',
+
+ // 81.FAQ
+ 'faq.pageTitle': 'Preguntas Frecuentes',
+ 'faq.whatIs.question': '¿Qué es Multiomix?',
+ 'faq.whatIs.answer': 'Multiomix es una plataforma open-source basada en la nube para investigar eventos genómicos y epigenómicos asociados con la modulación de la expresión génica, con enfoque en el descubrimiento de biomarcadores y el análisis multi-ómico en cáncer. Integra funciones de obtención, agregación, análisis y visualización de datos tanto públicos como cargados por el usuario.',
+ 'faq.whatIs.link': 'Artículo',
+ 'faq.analysisTypes.question': '¿Qué tipo de análisis puedo realizar en Multiomix?',
+ 'faq.analysisTypes.answer': 'Multiomix permite ejecutar análisis de correlación entre mRNA y otras capas ómicas no relacionadas con mRNA, particularmente miRNA, metilación de ADN y CNA. También incluye análisis de supervivencia, validaciones estadísticas, entrenamiento de modelos e inferencia sobre nuevos datasets. En cuanto a biomarcadores, la plataforma permite identificar, gestionar y evaluar firmas compuestas por diferentes variables ómicas, explorar su valor pronóstico o predictivo, entrenar modelos sobre esos biomarcadores y reutilizarlos para validación e inferencia en nuevas cohortes.',
+ 'faq.pipelines.question': '¿Qué pipelines principales y métodos estadísticos ofrece la plataforma?',
+ 'faq.pipelines.p1': 'La plataforma proporciona tres pipelines principales: miRNA-mRNA, metilación de ADN-mRNA y CNA-mRNA. En estos flujos de trabajo, los usuarios seleccionan datasets, filtros, método de correlación y ajuste de p-value, luego exploran resultados junto con información clínica y de seguimiento.',
+ 'faq.pipelines.p2': 'Para correlación, Multiomix soporta Pearson, Spearman y Kendall. Para corrección de pruebas múltiples, soporta Benjamini-Hochberg, Benjamini-Yekutieli y Bonferroni, entre otros. También se incluyen análisis de supervivencia como Kaplan-Meier y Log-rank para estimar el impacto biológico de los eventos detectados.',
+ 'faq.pipelines.p3': 'Un panel dedicado para gestión, optimización y evaluación de biomarcadores soporta biomarcadores compuestos por mRNA, miRNA, CNA y sitios de metilación. Permite entrenar modelos de clustering, Survival SVM y Random Survival Forest para evaluar el poder pronóstico o predictivo, y reutilizar modelos ya entrenados para nuevas validaciones e inferencias sin necesidad de reentrenarlos desde cero. Para biomarcadores existentes, la plataforma también ofrece optimización mediante múltiples métodos de selección de características.',
+
+ 'faq.uploadData.question': '¿Puedo cargar mis propios datos?',
+ 'faq.uploadData.answer': 'Sí. Multiomix permite cargar datasets propios de manera validada, con verificaciones de formato y consistencia. También ofrece cargas masivas para datasets grandes y una tabla interactiva con filtros, búsqueda, paginación, ordenamiento y etiquetas para gestionar sus datos.',
+
+ 'faq.datasetsPublic.question': '¿Multiomix incluye datos públicos listos para usar?',
+ 'faq.datasetsPublic.answer': 'Sí. La plataforma incluye datasets precargados obtenidos programáticamente desde cBioPortal. Esto permite trabajar con datos públicos y privados en el mismo entorno.',
+
+ 'faq.datasetsPreprocessing.question': '¿Cómo se incorporan y preprocesan los datasets de cBioPortal?',
+ 'faq.datasetsPreprocessing.p1': 'Los datasets de cBioPortal se sincronizan regularmente para garantizar consistencia de datos. Si existe una actualización que no detectamos, los usuarios pueden contactarnos directamente. Las moléculas duplicadas se eliminan para mantener limpio el dataset. Las muestras sin información para una molécula dada en un biomarcador son excluidas de modelos entrenados, validaciones estadísticas, experimentos de selección de características y pasos de inferencia.',
+ 'faq.datasetsPreprocessing.p2': 'Los datos clínicos también pasan por un preprocesamiento: los casos con valores NaN, vacíos o Null son filtrados. Adicionalmente, los casos con un evento pero con tiempo de supervivencia igual a cero son excluidos (pendiente de aclaración por parte de cBioPortal).',
+
+ 'faq.expertise.question': '¿Multiomix es solo para bioinformáticos expertos?',
+ 'faq.expertise.answer': 'No necesariamente. Multiomix fue diseñado para reducir barreras técnicas y proporcionar una experiencia accesible también para usuarios no expertos, sin sacrificar el rigor analítico. Su objetivo es acercar el descubrimiento de biomarcadores a una gama más amplia de perfiles de investigación mediante una interfaz amigable, documentación clara y guías de uso, dentro de un enfoque abierto y orientado a la democratización tecnológica.',
+
+ 'faq.performance.question': '¿Qué hace diferente a Multiomix en términos de rendimiento para análisis de correlación?',
+ 'faq.performance.answer': 'Para análisis de correlación a gran escala, Multiomix desarrolló su propia herramienta llamada GGCA, implementada en Rust para mejorar el rendimiento y el uso de memoria.',
+
+ 'faq.metaheuristics.question': '¿Cómo acelera Multiomix la ejecución de metaheurísticas para selección de características?',
+ 'faq.metaheuristics.answer': 'Multiomix incorpora optimizaciones de computación distribuida sobre Apache Spark para acelerar la evaluación de agentes metaheurísticos en procesos de selección de características. También incluye estrategias de distribución desarrolladas internamente diseñadas para maximizar el uso de recursos disponibles y lograr el mejor rendimiento posible.',
+ 'faq.metaheuristics.link': 'Fuente',
+
+ 'faq.integrations.question': '¿Qué herramientas del ecosistema integra Multiomix?',
+ 'faq.integrations.answer': 'Multiomix utiliza BioAPI y Modulector para parte de su funcionalidad. Ambas plataformas actúan como capas de abstracción para acceso estandarizado a datos biológicos. BioAPI expone nomenclatura génica, expresión e información de pathways mediante una API REST, mientras que Modulector centraliza datos de miRNA, genes y sitios de metilación, y ofrece servicios relacionados con evidencia y noticias de PubMed.',
+
+ 'faq.technologies.question': '¿Qué tecnologías utiliza internamente Multiomix?',
+ 'faq.technologies.answer': 'Multiomix está construido como una aplicación web en Python/Rust. Utiliza Django en el backend, React con TypeScript en el frontend, PostgreSQL para anotaciones, MongoDB para datasets precargados y Redis/WebSocket para ejecución asíncrona y notificaciones. Celery es utilizado para colas de tareas, con dependencias de Modulector y BioAPI.',
+
+ 'faq.privacy.question': '¿Cómo se maneja la privacidad de los datos cargados por el usuario?',
+ 'faq.privacy.answer': 'Los datos cargados se almacenan de forma segura y solo son accesibles para el usuario que los cargó. Una vez eliminados, los datos se borran permanentemente de nuestros servidores y no pueden recuperarse. Ningún tercero tiene acceso a datos privados de usuarios.',
+
+ 'faq.installation.question': '¿Puedo instalar Multiomix localmente?',
+ 'faq.installation.answer': 'Sí. Multiomix puede desplegarse localmente y su repositorio oficial incluye instrucciones de instalación y desarrollo, así como soporte para despliegues rápidos con Docker e instalación complementaria de BioAPI y Modulector. El proyecto se distribuye bajo la licencia GPL-3.0, la cual promueve transparencia, acceso al código fuente, adaptabilidad a necesidades específicas y colaboración abierta de la comunidad.',
+
+ 'faq.licenses.question': 'Librerías y herramientas con licencias',
+ 'faq.licenses.answer': 'Por razones legales y de transparencia, proporcionamos una lista de librerías y herramientas de terceros utilizadas en esta plataforma, junto con sus respectivas licencias. Esto garantiza cumplimiento y reconocimiento a las contribuciones de la comunidad open-source que impulsa nuestro ecosistema.',
+
+ 'faq.footer.links.siteMap': 'Mapa del sitio',
+ 'faq.footer.links.contact': 'Contáctenos',
+ 'faq.footer.links.terms': 'Términos y Condiciones',
+ 'faq.footer.links.privacy': 'Política de Privacidad',
+
+ // 82.FilesManager
+ 'files.manager.title': 'Administrador de archivos',
+ 'files.manager.input.label': 'Agregar un nuevo archivo',
+ 'files.manager.table.name': 'Nombre',
+ 'files.manager.table.description': 'Descripción',
+ 'files.manager.table.type': 'Tipo',
+ 'files.manager.table.date': 'Fecha',
+ 'files.manager.table.institutions': 'Instituciones',
+ 'files.manager.table.tag': 'Etiqueta',
+ 'files.manager.table.public': 'Público',
+ 'files.manager.table.actions': 'Acciones',
+
+ 'files.manager.filter.tag.placeholder': 'Seleccionar etiqueta existente',
+ 'files.manager.filter.visibility.all': 'Todos',
+ 'files.manager.filter.visibility.private': 'Privado',
+ 'files.manager.search.placeholder': 'Buscar por nombre',
+
+ 'files.manager.delete.tag.title': 'Eliminar etiqueta',
+ 'files.manager.delete.tag.confirm': '¿Está seguro de que desea eliminar la etiqueta "{tagName}"?',
+
+ 'files.manager.delete.file.title': 'Eliminar archivo',
+ 'files.manager.delete.file.confirm': '¿Está seguro de que desea eliminar el archivo {fileName}?',
+ 'files.manager.delete.file.warning.clinical': 'Este archivo será DESVINCULADO de todos los experimentos asociados',
+ 'files.manager.delete.file.warning.default': 'Todos los experimentos asociados a este archivo serán ELIMINADOS',
+
+ 'files.manager.upload.unloadWarning': 'Se está cargando un archivo. Si cierra la pestaña, la carga será cancelada.',
+
+ 'files.manager.error.invalidFormat': 'El archivo tiene un formato incorrecto: todas las columnas excepto el índice deben contener datos numéricos',
+
+ 'files.manager.tooltip.sharedWith': 'Este dataset está compartido con {list}',
+ 'files.manager.tooltip.publicVisible': 'Todos los usuarios de la plataforma pueden ver este archivo',
+ 'files.manager.tooltip.privateVisibility': 'Si esto está marcado, todos los usuarios de la plataforma pueden ver (pero no editar ni eliminar) este elemento',
+ 'files.manager.tooltip.indexColumn': 'La columna "{columnName}" será utilizada como índice',
+ 'files.manager.tooltip.edit': 'Editar',
+ 'files.manager.tooltip.download': 'Descargar archivo',
+ 'files.manager.tooltip.nanWarning': 'El dataset contiene valores NaN',
+
+ // Agregados
+ // BiomarkersPanel
+ 'biomarkersPanel.stopExperiment.header': 'Detener experimento',
+ 'biomarkersPanel.stopExperiment.content': '¿Está seguro de que desea detener el experimento {name}?',
+ 'biomarkersPanel.deleteModal.header': 'Eliminar biomarcador',
+ 'biomarkersPanel.deleteModal.content': '¿Está seguro de que desea eliminar el biomarcador {name}?',
+ 'biomarkersPanel.cloneModal.header': 'Clonar biomarcador',
+ 'biomarkersPanel.cloneModal.content': '¿Está seguro de que desea clonar el biomarcador "{name}"?',
+ 'biomarkersPanel.cloneModal.button': 'Clonar',
+
+ 'biomarkersPanel.table.headerTitle': 'Biomarcadores',
+ 'biomarkersPanel.table.searchPlaceholder': 'Buscar por nombre',
+ 'biomarkersPanel.table.column.tag': 'Etiqueta',
+ 'biomarkersPanel.table.column.origin': 'Origen',
+ 'biomarkersPanel.table.column.public': 'Público',
+ 'biomarkersPanel.table.column.shared': 'Compartido',
+
+ 'biomarkersPanel.table.addButton.title': 'Agregar nuevo biomarcador',
+
+ 'biomarkersPanel.icon.sharedInstitutions': 'Instituciones compartidas',
+ 'biomarkersPanel.icon.sharedUsers': 'Usuarios compartidos',
+ 'biomarkersPanel.icon.clone': 'Clonar biomarcador',
+ 'biomarkersPanel.icon.public': 'Todos los usuarios de la plataforma pueden ver este experimento',
+ 'biomarkersPanel.icon.notPublic': 'Si esto está marcado, todos los usuarios de la plataforma pueden ver (pero no editar ni eliminar) este elemento',
+
+ 'biomarkersPanel.confirmModal.loseData.header': 'Va a perder todos los datos ingresados',
+ 'biomarkersPanel.confirmModal.loseData.content': '¿Está seguro?',
+
+ 'biomarkersPanel.alert.errorCreating': '¡Error al crear biomarcador!',
+ 'biomarkersPanel.alert.errorEditing': '¡Error al editar biomarcador!',
+ 'biomarkersPanel.alert.successCreating': 'Biomarcador creado exitosamente',
+ 'biomarkersPanel.alert.successEditing': 'Biomarcador editado exitosamente',
+ 'biomarkersPanel.alert.successSubmitting': '¡Experimento enviado!',
+
+ 'biomarkersPanel.tags.noTag': 'Sin etiqueta',
+ 'biomarkersPanel.tags.label': 'Etiqueta',
+ 'biomarkersPanel.tags.placeholder': 'Seleccionar una etiqueta existente',
+}