The goal of this project is to build a flexible and easily extendable platform for exercises. Those exercises can then be loaded as web components into exercising apps or on educational websites. By providing high-level components for common exercise types like multiple-choice, even educators with few programming language should be able to create new exercises (introducing those components is a plan for the future).
This is a guido helping you to integrate new exercises. With the following information and a basic understanding of Stencil you are good to go.
This project uses i18next for translations. There are no global translation files, instead, every exercise has its own translations. This makes sure that the client does not load translations for exercises that are not displayed.
Put the translations inside ${pathToComponentFolder}/locales/${exerciseId}/
.
Add your translations folder to the assets of the component so that they will be included in the build.
@Component({
assetsDirs: ['locales/breadth-first-search']
})
Translations can be nested. If the following json was your translation file, you would reference the string "Hello World!" through "messages.greeting".
{
"messages": {
"greeting": "Hello World!"
}
}
Import i18next-wc
so that you can use i18next's web components for translations. Also,
you'll need to call loadTranslations
in the componentWillLoad
method. I decided to load translations within componentWillLoad
because this is the first lifecycle method that gets called. Therefore, the loading of the translations will start very early
which will reduce loading times. Remember to return or await the Promise returned by loadTranslations
so that the compnent
knows when the translations are loaded and the component can be displayed. Otherwise, the component might be rendered
before the translations are available which would look weird.
In order for every web component using its own translations, laadTranslations
will return an isolated (not global) object
containing just the translations that the component needs. The component uses it for getting its translations.
Exercises need to be documented so that this project provides metadata about its exercises. In fact, the app SharedExercises uses the generated JSON documentation for storing the exercises' metadata in the database.
- Use the documentation tag
tag
to add a comma separated list of tags identifying the subjects of an exercise. - Use the documentation tag
languages
to add a comma separated list with all languages supported by the exercise.
The following is a minimal example of an exercise component. You can use as a starting point for creating new exercises.
import {setupTranslations} from '../../../utils/translations';
import i18n from 'i18next';
import 'i18next-wc';
/**
* @tags example, getting_started
* @languages english, german
*/
@Component({
tag: 'exercise-example',
assetsDirs: ['locales/example']
})
export class Example implements ComponentInterface {
i18n: i18n;
async componentWillLoad(): Promise<void> {
this.i18n = await loadTranslations('example');
}
render() {
return (
<p>
<intl-message i18next={this.i18n} label="messages.greeting">
</intl-message>
</p>
);
}
}
To test your component run npm install
and npm start
. This will open the exercise picker component in the browser
where you can pick the exercise that should be displayed and manually tested.
- Tags only use lowercase letters and separate words with an underscore. Example: graph_theory
- The web components tags are prefixed with "exercise-". Example: "exercise-multiply-two-with-three"