Yagnesh
(Yagnesh Nayi)
March 28, 2025, 1:29pm
1
Hello,
I have a problem with translating some hard-coded content in MFE (Micro Frontend).
import { StrictDict } from '../../utils';
import singleSelect from '../images/singleSelect.png';
import multiSelect from '../images/multiSelect.png';
import dropdown from '../images/dropdown.png';
import numericalInput from '../images/numericalInput.png';
import textInput from '../images/textInput.png';
import advancedOlxTemplates from './advancedOlxTemplates';
import basicOlxTemplates from './basicOlxTemplates';
export const ProblemTypeKeys = StrictDict({
SINGLESELECT: 'multiplechoiceresponse',
MULTISELECT: 'choiceresponse',
DROPDOWN: 'optionresponse',
NUMERIC: 'numericalresponse',
TEXTINPUT: 'stringresponse',
ADVANCED: 'advanced',
} as const);
export type ProblemType = typeof ProblemTypeKeys[keyof typeof ProblemTypeKeys];
export const ProblemTypes = StrictDict({
This file has been truncated. show original
One solution I’ve thought of is creating custom IDs and default messages, and then trying to translate them that way or does anyone have any better ideas or suggestions for this kind of issue?
Thank You!
sarina
(Sarina Canelake)
March 31, 2025, 1:45pm
2
Would it be possible to make an upstream pull request to make these translatable strings?
braden
(Braden MacDonald (OpenCraft) - opencraft.com/help)
April 2, 2025, 5:45pm
3
I think that all of these title
, previewDescription
, and description
values can be changed to message IDs instead of hard-coded strings.
e.g.
export const ProblemTypes = StrictDict({
[ProblemTypeKeys.SINGLESELECT]: {
- title: 'Single select',
+ titleMessage: 'authoring.problemEditor.types.singleSelect.title',
preview: singleSelect,
- previewDescription: 'Learners must select the correct answer from a list of possible options.',
+ previewDescriptionMessage: 'authoring.problemEditor.types.singleSelect.previewDescription',
- description: 'Enter your single select answers below and select which choices are correct. Learners must choose one correct answer.',
+ descriptionMessage: 'authoring.problemEditor.types.singleSelect.description',
...
Then, they can be rendered like this:
<FormattedMessage id={data.previewDescriptionMessage} />
As long as the messages are defined in the messages.ts
files, it will work fine.
Yagnesh
(Yagnesh Nayi)
April 2, 2025, 6:04pm
4
@braden thank you for your suggestion! We’ve already completed this.
I noticed that Open edX translation WG is showing 100% translated and reviewed in Spanish, but it doesn’t seem like everything is fully done.
Yagnesh
(Yagnesh Nayi)
April 2, 2025, 6:10pm
5
@braden I’m still looking into a solution for this. Do you have any comments or thoughts
Hello Open edX Team,
I am currently working on implementing translations within Open edX. To do so, I’ve forked the Open edX translation repository and made some customizations. After building it, everything works fine, but the process is quite slow, especially when dealing with MFE (Micro Frontend).
My question is: Is there a more efficient way to handle so that I can see my custom translations reflected locally (in my dev environment) without having to rebuild everything each time?
For exa…
braden
(Braden MacDonald (OpenCraft) - opencraft.com/help)
April 2, 2025, 11:52pm
6
Can you please link to the PR? I want to make sure it’s fixed on master
, and I hadn’t seen it.
I agree you should be able to do that but I’ve never actually used our translations tooling so I’m not sure how to achieve it, sorry.
Yagnesh
(Yagnesh Nayi)
April 3, 2025, 12:09pm
7
I am working on the same part in the advanced list, facing a few issues related to JSX. Once I have resolved and tested this, I will submit a pull request. Additionally, I have another pull request on my list that I will also handle.
Yagnesh
(Yagnesh Nayi)
April 4, 2025, 8:39am
8
braden:
export const ProblemTypes = StrictDict({
[ProblemTypeKeys.SINGLESELECT]: {
- title: 'Single select',
+ titleMessage: 'authoring.problemEditor.types.singleSelect.title',
preview: singleSelect,
- previewDescription: 'Learners must select the correct answer from a list of possible options.',
+ previewDescriptionMessage: 'authoring.problemEditor.types.singleSelect.previewDescription',
- description: 'Enter your single select answers below and select which choices are correct. Learners must choose one correct answer.',
+ descriptionMessage: 'authoring.problemEditor.types.singleSelect.description',
...
We tried your solution, but it’s not working as expected. It also prints id also I don’t have much expertise in React.js, so I might be missing something.
After applying your solution, another issue has appeared: we are unable to edit the problem or add any types using options like single set, dropdown, etc.
@braden or @sarina Can you please connect us with a person who has experience in this area? We would like to reach out to them on Slack to troubleshoot and fix this issue together.
sarina
(Sarina Canelake)
April 4, 2025, 12:09pm
9
@Yagnesh I think the best thing to do would open your pull request as a draft, and get feedback on it.
2 Likes
IvoBranco
(Ivo Branco)
April 10, 2025, 7:51am
10
I just open a PR to fix it:
master
← fccn:igobranco/fix-translation-select-problem-type
opened 05:37PM - 09 Apr 25 UTC
The select problem type and advanced problem types didn't function correctly wit… h i18n/translation.
## Description
This PR fixes the translations/i18n of the "Select problem type"; and following screen "Advanced problem type" selection; and the following screen that shows a description of the problem.
Next some screenshots with highlighted section fixed:



## Supporting information
Any. Just private internal issues on [NAU platform](https://www.nau.edu.pt/pt/).
## Testing instructions
```bash
make pull_translations
```
Add to your language json file, example for pt-pt locale `src/i18n/messages/frontend-app-course-authoring/pt_PT.json`:
```json
"authoring.problemeditor.problemtype.title.singleselect": "Seleção única",
"authoring.problemeditor.problemtype.title.multiSelect": "Seleção múltipla",
"authoring.problemeditor.problemtype.title.dropdown": "Lista pendente",
"authoring.problemeditor.problemtype.title.numeric": "Entrada numérica",
"authoring.problemeditor.problemtype.title.textInput": "Entrada de texto",
"authoring.problemeditor.problemtype.title.advanced": "Problema avançado",
"authoring.problemeditor.settings.showanswertype.always": "Sempre",
"authoring.problemeditor.settings.showanswertype.answered": "Respondido",
"authoring.problemeditor.settings.showanswertype.attempted": "Tentativa ou atraso",
"authoring.problemeditor.settings.showanswertype.closed": "fechado",
"authoring.problemeditor.settings.showanswertype.finished": "terminado",
"authoring.problemeditor.settings.showanswertype.correct_or_past_due": "correcto_ou_atrasado",
"authoring.problemeditor.settings.showanswertype.past_due": "vencido",
"authoring.problemeditor.settings.showanswertype.never": "nunca",
"authoring.problemeditor.settings.showanswertype.after_attempts": "após_tentativas",
"authoring.problemeditor.settings.showanswertype.after_all_attempts": "após_todas_tentativas",
"authoring.problemeditor.settings.showanswertype.after_all_attempts_or_correct": "após_todas_as_tentativas_ou_correcção",
"authoring.problemeditor.settings.showanswertype.attempted_no_past_due": "tentativa_no_past_due",
"authoring.problemeditor.settings.RandomizationTypes.always": "sempre",
"authoring.problemeditor.settings.RandomizationTypes.never": "nunca",
"authoring.problemeditor.settings.RandomizationTypes.onreset": "onreset",
"authoring.problemeditor.settings.RandomizationTypes.perstudent": "por aluno",
"authoring.problemeditor.problemtype.previewDescription.singleselect": "Os alunos devem selecionar a resposta correta a partir de uma lista de opções possíveis.",
"authoring.problemeditor.problemtype.previewDescription.multiselect": "Os alunos devem selecionar todas as respostas corretas a partir de uma lista de opções possíveis.",
"authoring.problemeditor.problemtype.previewDescription.dropdown": "Os alunos devem selecionar a resposta correta a partir de uma lista de opções possíveis",
"authoring.problemeditor.problemtype.previewDescription.numeric": "Especificar uma ou mais respostas numéricas corretas, apresentadas num campo de resposta",
"authoring.problemeditor.problemtype.previewDescription.textinput": "Especificar uma ou mais respostas de texto corretas, incluindo números e caracteres especiais, apresentadas num campo de resposta.",
"authoring.problemeditor.problemtype.previewDescription.advanced": "Especificar um problema avançado.",
"authoring.problemeditor.problemtype.description.singleselect": "Introduza as suas respostas de seleção única abaixo e selecione as opções corretas. Os alunos devem escolher uma resposta correta.",
"authoring.problemeditor.problemtype.description.multiselect": "Introduza as suas respostas multi-selecionadas abaixo e selecione as opções corretas. Os alunos devem escolher todas as respostas corretas.",
"authoring.problemeditor.problemtype.description.dropdown": "Introduza as respostas da lista pendente abaixo e selecione a opção correta. Os alunos devem selecionar uma resposta correta.",
"authoring.problemeditor.problemtype.description.numeric": "Introduza as respostas numéricas corretas abaixo. Os alunos devem introduzir uma resposta correta.",
"authoring.problemeditor.problemtype.description.textinput": "Introduza as suas respostas de texto abaixo e selecione as opções corretas. Os alunos devem introduzir uma resposta correta.",
"authoring.problemeditor.problemtype.description.advanced": "Um tipo de problema avançado.",
"authoring.problemeditor.settings.advanceProblems.blank": "Problema em branco",
"authoring.problemeditor.settings.advanceProblems.circuitSchematic": "Construtor de esquemas de circuitos",
"authoring.problemeditor.settings.advanceProblems.jsInput": "Visualização e classificação JavaScript personalizadas",
"authoring.problemeditor.settings.advanceProblems.customGrader": "Entrada personalizada avaliada por Python",
"authoring.problemeditor.settings.advanceProblems.image": "Entrada mapeada por imagem",
"authoring.problemeditor.settings.advanceProblems.formula": "Entrada de expressão matemática",
"authoring.problemeditor.settings.advanceProblems.problemWithHint": "Problema com a sugestão adaptativa",
"authoring.problemeditor.settings.advanceProblems.status.empty": "",
"authoring.problemeditor.settings.advanceProblems.status.notSupported": "Não suportado",
"authoring.problemeditor.settings.advanceProblems.status.provisional": "Provisório",
```
## Other information
IvoBranco
(Ivo Branco)
April 10, 2025, 8:17am
11
Another PR to fix the translation extract process on the authoring MFE:
master
← fccn:igobranco/fix-extract-translations
opened 08:12AM - 10 Apr 25 UTC
Renamed all messages.ts files to messages.js to fix the translation extraction p… rocess using fedx-scripts.js and formatjs tool. This change increases the number of extracted strings, improving localization.
## Description
Currently the translation extract process uses the [`fedx-scripts.js`](https://github.com/openedx/frontend-build/blob/c70ef4e0a5e8702f7144f36b1b23195b94f5e09a/bin/fedx-scripts.js#L71-L81) that calls the `formatjs` tool.
The [`fedx-scripts.js`](https://github.com/openedx/frontend-build/blob/c70ef4e0a5e8702f7144f36b1b23195b94f5e09a/bin/fedx-scripts.js#L71-L81) assumes that all the i18n messages are on `.js` file extension.
By just changing the file extension on those files the extract translation process is fixed. Then more strings are sent to Transifex and this MFE is better localized for each language.
Before it extracts/ detect 1730 strings to be translated:
```bash
$ npm run i18n_extract && grep '"id"' temp/babel-plugin-formatjs/Default.messages.json | wc -l
> @edx/frontend-app-authoring@0.1.0 i18n_extract
> fedx-scripts formatjs extract
Running with resolved config:
/home/ibranco/projects/openedx/frontend-app-authoring/node_modules/@openedx/frontend-build/config/babel.config.js
1730
```
After extracts/ detect 2309 strings to be translated:
```
$ npm run i18n_extract && grep '"id"' temp/babel-plugin-formatjs/Default.messages.json | wc -l
> @edx/frontend-app-authoring@0.1.0 i18n_extract
> fedx-scripts formatjs extract
Running with resolved config:
/home/ibranco/projects/openedx/frontend-app-authoring/node_modules/@openedx/frontend-build/config/babel.config.js
[@formatjs/cli] [WARN] [FormatJS CLI] Duplicate message id: "course-authoring.course-libraries.tab.home.description-no-links", but the `description` and/or `defaultMessage` are different.[@formatjs/cli] [WARN] [FormatJS CLI] Duplicate message id: "course-authoring.library-authoring.component.advanced.olx-save", but the `description` and/or `defaultMessage` are different.[@formatjs/cli] [WARN] [FormatJS CLI] Duplicate message id: "course-authoring.library-authoring.create-library", but the `description` and/or `defaultMessage` are different.[@formatjs/cli] [WARN] [FormatJS CLI] Duplicate message id: "course-authoring.library-authoring.publish.error", but the `description` and/or `defaultMessage` are different.
2309
```
## Supporting information
Execute the script to find how many strings are extracted:
```bash
run i18n_extract && grep '"id"' temp/babel-plugin-formatjs/Default.messages.json | wc -l
```
## Testing instructions
For example the message with id `authoring.problemEditor.selectType.title` wasn't extracted.
With this PR it extracts, you can confirm by running:
```bash
grep "authoring.problemEditor.selectType.title" temp/babel-plugin-formatjs/Default.messages.json
```
To simulate the sent and download from Transifex you can execute:
```bash
make pull_translations
```
Edit manually a language, example pt-pt locale, edit the file `src/i18n/messages/frontend-app-course-authoring/pt_PT.json` and add:
```json
"authoring.problemEditor.selectType.title": "Selecionar o tipo de problema",
```
This will fix the header when editing problems:

## Other information
Related to: https://github.com/openedx/frontend-app-authoring/pull/1798
sarina
(Sarina Canelake)
April 10, 2025, 1:29pm
12
Thanks for these @IvoBranco ! It looks like they’re being reviewed already