diff --git a/docs/advanced/localization.md b/docs/advanced/localization.md index 854981c6d..04fb4c261 100644 --- a/docs/advanced/localization.md +++ b/docs/advanced/localization.md @@ -22,7 +22,6 @@ Some places of H5P cannot be localized at this time (this must be changed by Joubel): * Some strings in libraries that are hard-coded -* The H5P Hub content list and description ### Changing the language of the editor @@ -35,9 +34,10 @@ shows where this must be done: | 2. notify H5P editor client | Call `H5PEditor.render(contentId, language, ...)` with the language code you need. | | 3. properties of IIntegration | Pass a valid `translationCallback` of type `ITranslationFunction` to the constructor of `H5PEditor` | | 4. error messages emitted by @lumieducation/h5p-server | Catch errors of types `H5PError` and `AggregateH5PError` and localize the message property yourself. | +| 5. H5P Hub | When constructing `H5PEditor` set the option `enableHubLocalization` to true and load the namespace `hub` in your localization system. Call `H5PEditor.getContentTypeCache()` with a language or make sure that `req.language` is set in the get AJAX route when using `h5p-express`. | The [Express example](/packages/h5p-examples/src/express.ts) demonstrates how to -do 1,2 and 3. The [Express adapter for the Ajax endpoints](/packages/h5p-express/src/H5PAjaxRouter/H5PAjaxExpressRouter.ts) +do 1,2 and 3. The [Express adapter for the Ajax endpoints](/packages/h5p-express/src/H5PAjaxRouter/H5PAjaxExpressRouter.ts) already implements 4 but requires the `t(...)` function to be added to the `req` object. @@ -45,7 +45,7 @@ The language strings used by @lumieducation/h5p-server all follow the conventions of [i18next](https://www.npmjs.com/package/i18next) and it is a good library to perform the translation for cases 3 and 4. However, you are free to use whatever translation library you want as long as you make sure to pass a -valid `translationCallback` to `H5PEditor` (case 3) and add the required +valid `translationCallback` to `H5PEditor` (case 3+5) and add the required `t(...)` function to `req` (case 4). ### Initializing the JavaScript H5P client (in the browser) diff --git a/packages/h5p-examples/src/createH5PEditor.ts b/packages/h5p-examples/src/createH5PEditor.ts index da5172484..cb7ccaeda 100644 --- a/packages/h5p-examples/src/createH5PEditor.ts +++ b/packages/h5p-examples/src/createH5PEditor.ts @@ -134,7 +134,11 @@ export default async function createH5PEditor( : new H5P.fsImplementations.DirectoryTemporaryFileStorage( localTemporaryPath ), - translationCallback + translationCallback, + undefined, + { + enableHubLocalization: true + } ); // Set bucket lifecycle configuration for S3 temporary storage to make diff --git a/packages/h5p-examples/src/express.ts b/packages/h5p-examples/src/express.ts index 64af712d4..a7cbd0aaa 100644 --- a/packages/h5p-examples/src/express.ts +++ b/packages/h5p-examples/src/express.ts @@ -52,6 +52,7 @@ const start = async (): Promise => { ns: [ 'client', 'copyright-semantics', + 'hub', 'metadata-semantics', 'mongo-s3-content-storage', 's3-temporary-storage', diff --git a/packages/h5p-express/src/H5PAjaxRouter/H5PAjaxExpressController.ts b/packages/h5p-express/src/H5PAjaxRouter/H5PAjaxExpressController.ts index e30ee5439..dc3a51579 100644 --- a/packages/h5p-express/src/H5PAjaxRouter/H5PAjaxExpressController.ts +++ b/packages/h5p-express/src/H5PAjaxRouter/H5PAjaxExpressController.ts @@ -32,7 +32,7 @@ export default class H5PAjaxExpressController { req.query.machineName as string, req.query.majorVersion as string, req.query.minorVersion as string, - req.query.language as string, + (req as any).language ?? (req.query.language as string), req.user ); res.status(200).send(result); diff --git a/packages/h5p-rest-example-server/src/createH5PEditor.ts b/packages/h5p-rest-example-server/src/createH5PEditor.ts index 00b1c067d..729c39ad0 100644 --- a/packages/h5p-rest-example-server/src/createH5PEditor.ts +++ b/packages/h5p-rest-example-server/src/createH5PEditor.ts @@ -103,7 +103,11 @@ export default async function createH5PEditor( : new H5P.fsImplementations.DirectoryTemporaryFileStorage( localTemporaryPath ), - translationCallback + translationCallback, + undefined, + { + enableHubLocalization: true + } ); // Set bucket lifecycle configuration for S3 temporary storage to make diff --git a/packages/h5p-rest-example-server/src/index.ts b/packages/h5p-rest-example-server/src/index.ts index d0ae9bef1..b593228ae 100644 --- a/packages/h5p-rest-example-server/src/index.ts +++ b/packages/h5p-rest-example-server/src/index.ts @@ -50,6 +50,7 @@ const start = async (): Promise => { ns: [ 'client', 'copyright-semantics', + 'hub', 'metadata-semantics', 'mongo-s3-content-storage', 's3-temporary-storage', diff --git a/packages/h5p-server/assets/translations/hub/de.json b/packages/h5p-server/assets/translations/hub/de.json new file mode 100644 index 000000000..f7b69afc7 --- /dev/null +++ b/packages/h5p-server/assets/translations/hub/de.json @@ -0,0 +1,325 @@ +{ + "H5P_Accordion": { + "title": "Akkordeon (Accordion)", + "summary": "Erstellen Sie vertikal gestapelte erweiterbare Elemente", + "description": "Reduzieren Sie die Textmenge, die den Lesern präsentiert wird, indem Sie dieses reaktionsschnelle Akkordeon verwenden. Die Leser entscheiden, welche Überschriften sie genauer betrachten möchten, indem sie den Titel erweitern. Hervorragend geeignet, um einen Überblick mit optionalen ausführlichen Erklärungen zu bieten.", + "keywords": { + "accordion": "Akkordeon", + "collapsible_text": "zusammenklappbarer Text" + } + }, + "H5P_ArithmeticQuiz": { + "title": "Arithmetisches Quiz (Arithmetic Quiz)", + "summary": "Erstellen Sie zeitbasierte arithmetische Tests", + "description": "Erstellen Sie arithmetische Tests, die aus Multiple-Choice-Fragen bestehen. Als Autor müssen Sie lediglich Art und Länge des Quiz festlegen. Benutzer verfolgen die Punktzahl und die Zeit, die sie beim Lösen des Quiz aufgewendet haben.", + "keywords": { + "math": "Mathematik", + "arithmetic_quiz": "Rechenquiz", + "countdown": "Countdown" + } + }, + "H5P_Chart": { + "title": "Diagramm (Chart)", + "summary": "Generieren Sie schnell Balken- und Kreisdiagramme", + "description": "Müssen Sie einfache statistische Daten grafisch darstellen, ohne das Bildmaterial manuell zu erstellen? Diagramm ist Ihre Antwort.", + "keywords": { + "chart": "Diagramm", + "bar_chart": "Balkendiagramm", + "pie_chart": "Kuchendiagramm", + "graph": "Graph" + } + }, + "H5P_Collage": { + "title": "Kleben (Collage)", + "summary": "Erstellen Sie eine Collage aus mehreren Bildern", + "description": "Mit dem Collage-Werkzeug können Sie Bilder in einer beruhigenden Komposition organisieren.", + "keywords": { "collage": "Collage", "image": "Bild" } + }, + "H5P_Column": { + "title": "Spalte (Column)", + "summary": "Organisieren Sie H5P-Inhalte in einem Spaltenlayout", + "description": "Organisieren Sie Ihren Inhaltstyp mit H5P Column in einem Spaltenlayout. Inhaltstypen, die sich mit ähnlichem Material befassen oder ein gemeinsames Thema haben, können jetzt zu einer kohärenten Lernerfahrung zusammengefasst werden. Darüber hinaus können Autoren kreativ sein, indem sie fast alle vorhandenen H5P-Inhaltstypen kombinieren.", + "keywords": { + "column": "Säule", + "layout": "Layout", + "compound": "Verbindung" + } + }, + "H5P_CoursePresentation": { + "title": "Kurspräsentation (Course Presentation)", + "summary": "Erstellen Sie eine Präsentation mit interaktiven Folien", + "description": "Die Kurspräsentationen bestehen aus Folien mit Multimedia, Text und vielen verschiedenen Arten von Interaktionen wie interaktiven Zusammenfassungen, Multiple-Choice-Fragen und interaktiven Videos. Die Lernenden können neues interaktives Lernmaterial erleben und ihr Wissen und Gedächtnis in Kurspräsentationen testen. Wie immer bei H5P können Inhalte in Webbrowsern bearbeitet werden, und der Aktivitätstyp \"Kurspräsentation\" enthält ein auf Drag & Drop basierendes WYSIWYG-Authoring-Tool. Eine typische Verwendung der Kurspräsentationsaktivität besteht darin, einige Folien zu verwenden, um ein Thema vorzustellen, und diesen mit einigen weiteren Folien zu folgen, in denen das Wissen des Benutzers getestet wird. Kurspräsentationen können jedoch auf viele verschiedene Arten verwendet werden, beispielsweise als Präsentationswerkzeug für den Unterricht oder als Spiel, bei dem die übliche Navigation durch Navigationsschaltflächen oben auf den Folien ersetzt wird, damit der Benutzer Entscheidungen treffen und die Konsequenzen sehen kann ihrer Entscheidungen.", + "keywords": { + "course_presentation": "Kurspräsentation", + "slides": "Folien", + "powerpoint": "Power Point" + } + }, + "H5P_Dialogcards": { + "title": "Dialogkarten (Dialog Cards)", + "summary": "Erstellen Sie textbasierte Wendekarten", + "description": "Dialogkarten können als Übung verwendet werden, um den Lernenden das Auswendiglernen von Wörtern, Ausdrücken oder Sätzen zu erleichtern. Auf der Vorderseite der Karte befindet sich ein Hinweis auf ein Wort oder einen Ausdruck. Durch Drehen der Karte zeigt der Lernende ein entsprechendes Wort oder einen entsprechenden Ausdruck. Dialogkarten können beim Sprachenlernen verwendet werden, um mathematische Probleme darzustellen oder um den Lernenden zu helfen, sich an Fakten wie historische Ereignisse, Formeln oder Namen zu erinnern.", + "keywords": { "dialog_cards": "Dialogkarten" } + }, + "H5P_DocumentationTool": { + "title": "Dokumentationswerkzeug (Documentation Tool)", + "summary": "Erstellen Sie einen Formularassistenten mit Textexport", + "description": "Das Dokumentationstool soll die Erstellung von Bewertungsassistenten für zielgerichtete Aktivitäten vereinfachen. Es kann auch als Formularassistent verwendet werden. Während der Bearbeitung kann der Autor dem Assistenten mehrere Schritte hinzufügen. In jedem Schritt kann der Autor definieren, welcher Inhalt in diesen Schritt einfließt. Inhalt kann Klartext, Eingabefelder, Zieldefinition und Zielbewertung sein. Nach der Veröffentlichung wird der Endbenutzer durch die Schritte des Assistenten geführt. Im letzten Schritt des Assistenten kann der Benutzer ein Dokument mit allen übermittelten Eingaben erstellen. Dieses Dokument kann heruntergeladen werden. Das Dokumentationstool reagiert vollständig und funktioniert sowohl auf kleineren Bildschirmen als auch auf Ihrem Desktop.", + "keywords": { "dialog_cards": "Dialogkarten" } + }, + "H5P_DragQuestion": { + "title": "Drag & Drop", + "summary": "Erstellen Sie Drag & Drop-Aufgaben mit Bildern", + "description": "Drag & Drop-Fragen ermöglichen es dem Lernenden, zwei oder mehr Elemente zuzuordnen und logische Verbindungen auf visuelle Weise herzustellen. Erstellen Sie Drag & Drop-Fragen, indem Sie Text und Bilder als ziehbare Alternativen verwenden. H5P Drag & Drop-Fragen unterstützen Eins-zu-Eins-, Eins-zu-Viele-, Viele-zu-Eins- und Viele-zu-Viele-Beziehungen zwischen Fragen und Antworten.", + "keywords": { "drag_and drop": "Drag & Drop" } + }, + "H5P_DragText": { + "title": "Ziehen Sie die Wörter (Drag the Words)", + "summary": "Erstellen Sie textbasierte Drag & Drop-Aufgaben", + "description": "Mit Drag the Words können Inhaltsdesigner Textausdrücke mit fehlenden Textteilen erstellen. Der Endbenutzer zieht einen fehlenden Text an die richtige Stelle, um einen vollständigen Ausdruck zu bilden. Kann verwendet werden, um zu überprüfen, ob sich der Benutzer an einen gelesenen Text erinnert oder ob er etwas versteht. Hilft dem Benutzer beim Durchdenken eines Textes. Es ist super einfach, eine Drag-the-Words-Aufgabe zu erstellen. Der Editor schreibt nur den Text und schließt die Wörter, die ziehbar sein sollen, mit Sternchen wie * draggableWord * ein.", + "keywords": { "drag": "ziehen", "words": "Wörter" } + }, + "H5P_Blanks": { + "title": "Füllen Sie die Lücken aus (Fill in the Blanks)", + "summary": "Erstellen Sie eine Aufgabe mit fehlenden Wörtern in einem Text", + "description": "Die Lernenden geben die fehlenden Wörter in einen Text ein. Dem Lernenden wird eine Lösung angezeigt, nachdem er alle fehlenden Wörter eingegeben hat oder je nach den Einstellungen nach jedem Wort. Autoren geben Text ein und markieren Wörter, die durch ein Sternchen ersetzt werden sollen. Zusätzlich zum Erlernen der Muttersprache und der zweiten Sprache kann das Ausfüllen der Lücken verwendet werden, um die Fähigkeit des Lernenden zu testen, Fakten zu reproduzieren oder mathematische Schlussfolgerungen zu ziehen.", + "keywords": { "fill": "füllen", "blanks": "Leerzeichen", "text": "Text" } + }, + "H5P_ImageHotspotQuestion": { + "title": "Finden Sie den Hotspot (Find the Hotspot)", + "summary": "Erstellen Sie Bild-Hotspots, die Benutzer finden können", + "description": "Dieser Inhaltstyp ermöglicht es Endbenutzern, irgendwo auf ein Bild zu drücken und Feedback zu erhalten, ob dies gemäß der Aufgabenbeschreibung richtig oder falsch war. Der Autor lädt ein Bild hoch und definiert verschiedene Hotspots, die Details oder Abschnitten des Bildes entsprechen. Hotspots können entweder als richtig oder falsch definiert werden, und der Autor gibt in beiden Fällen den entsprechenden Feedback-Text an. Der Autor kann auch ein Feedback definieren, wenn der Endbenutzer auf eine Stelle drückt, die weder als korrekter noch als falscher Hotspot definiert ist.", + "keywords": { "find": "finden", "hotspot": "Hotspot", "image": "Bild" } + }, + "H5P_GuessTheAnswer": { + "title": "Errate die Antwort (Guess the Answer)", + "summary": "Erstellen Sie ein Bild mit einer Frage und Antwort", + "description": "Mit diesem Inhaltstyp können Autoren ein Bild hochladen und eine geeignete Beschreibung hinzufügen. Endbenutzer können die Antwort erraten und auf die Leiste unter dem Bild drücken, um die richtige Antwort anzuzeigen.", + "keywords": { "guess": "vermuten", "answer": "Antworten" } + }, + "H5P_IFrameEmbed": { + "title": "Iframe Embedder", + "summary": "Einbetten aus einer URL oder einer Reihe von Dateien", + "description": "Mit dem Iframe-Einbettungsprogramm können Sie auf einfache Weise ein H5P aus bereits vorhandenen JavaScript-Anwendungen erstellen.", + "keywords": { "embed": "einbetten", "iframe": "iframe" } + }, + "H5P_InteractiveVideo": { + "title": "Interaktives Video (Interactive Video)", + "summary": "Erstellen Sie mit Interaktionen angereicherte Videos", + "description": "Fügen Sie Ihrem Video Interaktivität mit Erklärungen, zusätzlichen Bildern, Tabellen, Ausfüllen der Lücke und Multiple-Choice-Fragen hinzu. Quizfragen unterstützen die Adaptivität, dh Sie können basierend auf den Benutzereingaben zu einem anderen Teil des Videos springen. Interaktive Zusammenfassungen können am Ende des Videos hinzugefügt werden. Interaktive Videos werden mit dem H5P-Authoring-Tool in einem Standard-Webbrowser erstellt und bearbeitet.", + "keywords": { "interactive": "interaktiv", "video": "Video" } + }, + "H5P_MarkTheWords": { + "title": "Markiere die Wörter (Mark the Words)", + "summary": "Erstellen Sie eine Aufgabe, bei der Benutzer Wörter hervorheben", + "description": "Durch Markieren der Wörter können Inhaltsdesigner Textausdrücke mit einem definierten Satz korrekter Wörter erstellen. Der Endbenutzer hebt Wörter gemäß der Aufgabenbeschreibung hervor und erhält eine Punktzahl. Für den Editor ist es super einfach, eine Klick-Wort-Herausforderung zu erstellen. Der Editor gibt den Text ein und fügt die Wörter, auf die der Benutzer klicken soll, die richtigen Antworten in einem Sternchen wie * korrektWord * ein.", + "keywords": { "mark": "Kennzeichen", "words": "Wörter" } + }, + "H5P_MemoryGame": { + "title": "Gedächtnisspiel (Memory Game)", + "summary": "Erstellen Sie das klassische Bildpaarungsspiel", + "description": "Erstellen Sie Ihre eigenen Memory-Spiele und testen Sie den Speicher der Benutzer Ihrer Website mit diesem einfachen, aber schönen HTML5-Spiel.", + "keywords": { "memory": "Erinnerung", "game": "Spiel", "cards": "Karten" } + }, + "H5P_MultiChoice": { + "title": "Multiple Choice", + "summary": "Erstellen Sie flexible Multiple-Choice-Fragen", + "description": "Multiple-Choice-Fragen können ein wirksames Bewertungsinstrument sein. Der Lernende erhält sofort ein Leistungsfeedback. Die H5P-Multiple-Choice-Fragen können eine oder mehrere richtige Optionen pro Frage enthalten.", + "keywords": { "multiple": "mehrere", "choice": "Wahl", "quiz": "Quiz" } + }, + "H5P_PersonalityQuiz": { + "title": "Persönlichkeits-Quiz (Personality Quiz)", + "summary": "Erstellen Sie Persönlichkeitstests", + "description": "In diesem Inhaltstyp definiert der Autor eine Reihe von Fragen mit Alternativen, wobei jede Alternative mit einer oder mehreren Persönlichkeiten verglichen wird. Am Ende des Quiz sieht der Endbenutzer, welche Persönlichkeit am besten passt. Es gibt verschiedene Möglichkeiten, dieses Quiz optisch ansprechend zu gestalten, z. Darstellung von Fragen, Alternativen und Persönlichkeiten mithilfe von Bildern.", + "keywords": { "personality": "Persönlichkeit", "quiz": "Quiz" } + }, + "H5P_Questionnaire": { + "title": "Der Fragebogen (Questionnaire)", + "summary": "Erstellen Sie einen Fragebogen, um Feedback zu erhalten", + "description": "Erhalten Sie Feedback und stellen Sie mit dem Fragebogen offene Fragen in interaktiven Videos und anderen Inhaltstypen. Der Fragebogen stellt die Antworten des Benutzers über eine xAPI-Integration zur Verfügung. Dies bedeutet, dass Websitebesitzer die Antworten auf viele verschiedene Arten speichern können. Antworten können in einem LRS gespeichert werden, der eigene Speicher der Site oder ein Skript kann die E-Mail-Adresse abrufen und zum Senden einer E-Mail an den Benutzer verwenden. Auf H5P.org werden Antworten in Google Analytics gespeichert.", + "keywords": { "questionnaire": "Fragebogen" } + }, + "H5P_QuestionSet": { + "title": "Quiz (Question Set) (Quiz (Question Set))", + "summary": "Erstellen Sie eine Folge verschiedener Fragetypen", + "description": "Der Fragensatz ist Ihr typischer Quizinhaltstyp. Es ermöglicht dem Lernenden, eine Folge verschiedener Fragetypen wie Mehrfachauswahl, Ziehen und Ablegen zu lösen und die Lücken in einem Fragensatz auszufüllen. Als Autor gibt es viele Einstellungen, mit denen Sie festlegen können, dass es sich genau so verhält, wie Sie es möchten. Sie können beispielsweise den Fragensatz mit Hintergrundbildern anpassen und einen Prozentsatz für das Bestehen des Lernenden definieren. Mit dem Fragensatz können Sie auch Videos hinzufügen, die am Ende abgespielt werden. Ein Video für den Erfolg, ein anderes, wenn der Lernende den Test nicht besteht. Dies könnte die Lernenden motivieren, es erneut zu versuchen, wenn sie versagen, damit sie das Erfolgsvideo sehen können.", + "keywords": { + "question_set": "Fragensatz", + "collection": "Sammlung", + "quiz": "Quiz" + } + }, + "H5P_SingleChoiceSet": { + "title": "Single Choice Set", + "summary": "Erstellen Sie Fragen mit einer richtigen Antwort", + "description": "Mit dem Single-Choice-Set können Inhaltsdesigner Fragensets mit einer richtigen Antwort pro Frage erstellen. Der Endbenutzer erhält nach dem Absenden jeder Antwort sofort eine Rückmeldung.", + "keywords": { "collection": "Sammlung", "quiz": "Quiz", "choice": "Wahl" } + }, + "H5P_Summary": { + "title": "Zusammenfassung (Summary)", + "summary": "Erstellen Sie Aufgaben mit einer Liste von Anweisungen", + "description": "Zusammenfassungen helfen dem Lernenden, sich wichtige Informationen in einem Text, Video oder einer Präsentation zu merken, indem sie aktiv eine Zusammenfassung über das jeweilige Thema erstellen. Wenn der Lernende eine Zusammenfassung ausgefüllt hat, wird eine vollständige Liste der wichtigsten Aussagen zum Thema angezeigt.", + "keywords": { "summary": "Zusammenfassung" } + }, + "H5P_Timeline": { + "title": "Zeitleiste (Timeline)", + "summary": "Erstellen Sie eine Zeitleiste mit Ereignissen mit Multimedia", + "description": "Dies ist Timeline.js, das von Knight Lab entwickelt wurde und als H5P-Inhaltstyp verpackt ist, damit Timelines leicht bearbeitet, geteilt und wiederverwendet werden können. Mit dem Inhaltstyp \"Zeitleiste\" können Sie eine Folge von Ereignissen in chronologischer Reihenfolge platzieren. Für jede Veranstaltung können Sie Bilder und Texte hinzufügen. Sie können auch Assets von Twitter, YouTube, Flickr, Vimeo, Google Maps und SoundCloud einschließen.", + "keywords": { "timeline": "Zeitleiste", "slider": "Schieberegler" } + }, + "H5P_TrueFalse": { + "title": "Richtig / Falsch-Frage (True/False Question)", + "summary": "Erstellen Sie Richtig / Falsch-Fragen", + "description": "Richtig / Falsch Frage ist ein einfacher und unkomplizierter Inhaltstyp, der von selbst funktionieren oder in andere Inhaltstypen wie die Kurspräsentation eingefügt werden kann. Eine komplexere Frage kann durch Hinzufügen eines Bildes oder eines Videos erstellt werden.", + "keywords": { "true": "wahr", "false": "falsch" } + }, + "H5P_ImageHotspots": { + "title": "Bild-Hotspots (Image Hotspots)", + "summary": "Erstellen Sie ein Bild mit mehreren Info-Hotspots", + "description": "Mit Bild-Hotspots können Sie ein Bild mit interaktiven Hotspots erstellen. Wenn der Benutzer einen Hotspot drückt, wird ein Popup mit einer Kopfzeile und Text oder Video angezeigt. Mit dem H5P-Editor können Sie beliebig viele Hotspots hinzufügen.", + "keywords": { "image": "Bild", "hotspot": "Hotspot" } + }, + "H5P_ImageMultipleHotspotQuestion": { + "title": "Mehrere Hotspots suchen (Find Multiple Hotspots)", + "summary": "Erstellen Sie viele Hotspots, die Benutzer finden können", + "description": "Ein kostenloser HTML5-basierter Fragetyp, mit dem Kreative einen bildbasierten Test erstellen können, bei dem der Lernende die richtigen Stellen auf einem Bild finden soll. Verwenden Sie diesen Inhaltstyp mit dem H5P-Plugin für WordPress, Moodle oder Drupal, um Ihre Benutzer herauszufordern." + }, + "H5P_ImageJuxtaposition": { + "title": "Bild-Nebeneinander (Image Juxtaposition)", + "summary": "Erstellen Sie interaktive Bilder", + "description": "Ein kostenloser HTML5-basierter Bildinhaltstyp, mit dem Benutzer zwei Bilder interaktiv vergleichen können. Erzählen Sie Ihre Bildergeschichten mit H5P und Image Juxtaposition auf WordPress, Moodle oder Drupal." + }, + "H5P_Audio": { + "title": "Audio", + "summary": "Laden Sie eine Audioaufnahme hoch", + "description": "Laden Sie eine Audioaufnahme in .mp3, .wav, .ogg hoch oder stellen Sie den Link für eine Audioaufnahme bereit." + }, + "H5P_AudioRecorder": { + "title": "Audiorecorder (Audio Recorder)", + "summary": "Erstellen Sie eine Audioaufnahme", + "description": "Ein HTML5-Audiorecorder. Nehmen Sie Ihre Stimme auf und spielen Sie eine WAV-Datei Ihrer Aufnahme ab oder laden Sie sie herunter. Verwenden Sie das H5P-Plugin, um den H5P-Audiorecorder für Ihre Drupal-, Wordpress- oder Moodle-Site zu erstellen.", + "keywords": { "audio": "Audio-", "recorder": "Recorder" } + }, + "H5P_SpeakTheWords": { + "title": "Sprechen Sie die Wörter (Speak the Words)", + "summary": "Beantworten Sie eine Frage mit Ihrer Stimme (Chrome only)", + "description": "Speak the Words wird nur in Browsern unterstützt, die die Web Speech API implementieren (Chrome-Browser, außer unter iOS). Sie benötigen ein Mikrofon, um die Frage zu beantworten. Stellen Sie den Benutzern eine Frage und lassen Sie sie mit ihrer Stimme antworten. Sie können mehrere richtige Antworten auswählen. Der Benutzer kann sehen, als was seine Wörter interpretiert wurden und wie nah es an den richtigen Antworten war.", + "keywords": { + "language": "Sprache", + "translation": "Übersetzung", + "voice": "Stimme", + "recognition": "Anerkennung", + "speech": "Rede", + "mic": "wenig", + "microphone": "Mikrofon" + } + }, + "H5P_Agamotto": { + "title": "Agamotto (Image Blender) (Agamotto (Image Blender))", + "summary": "Präsentieren Sie eine Folge von Bildern und Erklärungen", + "description": "Präsentieren Sie eine Folge von Bildern, die Personen nacheinander betrachten sollen, z. Fotos eines Elements, das sich im Laufe der Zeit ändert, Schaltpläne oder Karten, die in verschiedenen Ebenen organisiert sind, oder Bilder, die immer mehr Details enthüllen.", + "keywords": { + "image": "Bild", + "images": "Bilder", + "transition": "Überleitung" + } + }, + "H5P_ImageSequencing": { + "title": "Bildsequenzierung (Image Sequencing)", + "summary": "Platzieren Sie die Bilder in der richtigen Reihenfolge", + "description": "Ein kostenloser HTML5-basierter Inhaltstyp für die Bildsequenzierung, mit dem Autoren dem Spiel eine Sequenz ihrer eigenen Bilder (und eine optionale Bildbeschreibung) in einer bestimmten Reihenfolge hinzufügen können. Die Reihenfolge der Bilder wird zufällig festgelegt und die Spieler müssen sie basierend auf der Aufgabenbeschreibung neu anordnen.", + "keywords": { + "image": "Bild", + "sequence": "Reihenfolge", + "order": "bestellen" + } + }, + "H5P_Flashcards": { + "title": "Karteikarten (Flashcards)", + "summary": "Erstellen Sie stilvolle und moderne Karteikarten", + "description": "Mit diesem Inhaltstyp können Autoren eine einzelne Karteikarte oder einen Satz Karteikarten erstellen, auf denen auf jeder Karte Bilder mit Fragen und Antworten gepaart sind. Die Lernenden müssen das Textfeld ausfüllen und dann die Richtigkeit ihrer Lösung überprüfen.", + "keywords": { "cards": "Karten", "animation": "Animation" } + }, + "H5P_SpeakTheWordsSet": { + "title": "Sprechen Sie das Wortset (Speak the Words Set)", + "summary": "Erstellen Sie eine Reihe von Fragen, die per Sprache beantwortet werden (Chrome only)", + "description": "Speak the Words Set wird nur in Browsern unterstützt, die die Web Speech API implementieren (Chrome-Browser, außer auf iOS). Sie benötigen ein Mikrofon, um die Frage zu beantworten. Erstellen Sie eine Reihe von Fragen, die die Lernenden mit ihrer Stimme beantworten können. Sie können mehrere richtige Antworten auswählen. Der Benutzer kann sehen, als was seine Wörter interpretiert wurden und wie nah es an den richtigen Antworten war.", + "keywords": { + "language": "Sprache", + "translation": "Übersetzung", + "voice": "Stimme", + "quiz": "Quiz", + "set": "einstellen", + "recognition": "Anerkennung", + "mic": "wenig", + "microphone": "Mikrofon" + } + }, + "H5P_ImageSlider": { + "title": "Bildschieberegler (Image Slider)", + "summary": "Erstellen Sie ganz einfach einen Bildschieberegler", + "description": "Präsentieren Sie Ihre Bilder mit Leichtigkeit auf ansprechende Weise. Autoren müssen lediglich Bilder hochladen und alternative Texte für die Bilder bereitstellen.\r\n\r\nDie nächsten beiden Bilder sind immer vorinstalliert, sodass das Umschalten zwischen den Bildern in der Regel ohne Verzögerung beim Laden des nächsten Bilds schnell erfolgt.\r\n\r\nBilder können als Teil der Seite oder im Vollbildmodus angezeigt werden. Bei Verwendung als Teil der Seite wählt das System abhängig von den verwendeten Bildern ein festes Seitenverhältnis aus. Autoren können beschließen, Seitenverhältnisse unterschiedlich zu behandeln.", + "keywords": { + "image": "Bild", + "images": "Bilder", + "slider": "Schieberegler", + "carousel": "Karussell" + } + }, + "H5P_Essay": { + "title": "Essay", + "summary": "Erstellen Sie einen Aufsatz mit sofortigem Feedback", + "description": "In diesem Inhaltstyp definiert der Autor eine Reihe von Schlüsselwörtern, die wichtige Aspekte eines Themas darstellen. Diese Schlüsselwörter werden mit einem von den Schülern verfassten Text abgeglichen und können verwendet werden, um sofort Feedback zu geben. Entweder wird vorgeschlagen, bestimmte Themendetails zu überarbeiten, wenn ein Schlüsselwort fehlt, oder es werden die Ideen des Schülers bestätigt, wenn der Text ein Schlüsselwort enthält.\r\n", + "keywords": { "Essay": "Aufsatz" } + }, + "H5P_ImagePair": { + "title": "Bildkopplung (Image Pairing)", + "summary": "Drag & Drop-Bild-Matching-Spiel", + "description": "Die Bildpaarung ist eine einfache und effektive Aktivität, bei der die Lernenden Bildpaare abgleichen müssen. Da es nicht erforderlich ist, dass beide Bilder in einem Paar gleich sind, können Autoren auch das Verständnis einer Beziehung zwischen zwei verschiedenen Bildern testen.", + "keywords": { "image_images matching pair": "Bild Bilder passendes Paar" } + }, + "H5P_Dictation": { + "title": "Diktat (Dictation)", + "summary": "Erstellen Sie ein Diktat mit sofortigem Feedback", + "description": "Sie können Audio-Samples hinzufügen, die einen Satz zum Diktieren enthalten, und die richtige Transkription eingeben. Ihre Schüler können sich die Beispiele anhören und das, was sie gehört haben, in ein Textfeld eingeben. Ihre Antworten werden automatisch ausgewertet. Mit verschiedenen Optionen können Sie den Schwierigkeitsgrad der Übung steuern. Sie können optional ein zweites Audio-Sample für einen Satz hinzufügen, der eine langsam gesprochene Version enthalten kann. Sie können auch ein Limit für die Häufigkeit festlegen, mit der ein Sample gespielt werden kann, festlegen, ob Interpunktion für die Bewertung relevant sein soll, und entscheiden, ob kleine Fehler wie Tippfehler als kein Fehler, vollständiger Fehler oder nur als halber Fehler gewertet werden sollen.", + "keywords": { "language": "Sprache", "audio": "Audio-" } + }, + "H5P_BranchingScenario": { + "title": "Verzweigungsszenario (beta) (Branching Scenario (beta))", + "summary": "Erstellen Sie Dilemmata und selbstgesteuertes Lernen", + "description": "Das Verzweigungsszenario ermöglicht es den Autoren, den Lernenden eine Vielzahl von interaktiven Inhalten und Auswahlmöglichkeiten zu präsentieren. Die Entscheidungen, die die Lernenden treffen, bestimmen den nächsten Inhalt, den sie sehen. Kann verwendet werden, um Dilemmata, ernsthafte Spiele und selbstgesteuertes Lernen zu erstellen." + }, + "H5P_ThreeImage": { + "title": "Virtuelle Tour (360) (Virtual Tour (360))", + "summary": "Erstellen Sie 360 Umgebungen mit Interaktionen", + "description": "360 (gleichwinklig) und normale Bilder können mit Interaktivitäten wie Erklärungen, Videos, Sounds und interaktiven Fragen angereichert werden. Die Bilder erstellen Szenen, die auch miteinander verknüpft werden können, um dem Benutzer den Eindruck zu vermitteln, sich zwischen Umgebungen oder zwischen verschiedenen Blickwinkeln innerhalb derselben Umgebung zu bewegen." + }, + "H5P_FindTheWords": { + "title": "Finde die Wörter (Find the words)", + "summary": "Rasterwortsuchspiel", + "description": "Eine kostenlose HTML5-basierte Wortsuchaktivität, mit der Autoren eine Liste von Wörtern erstellen können, die in einem Raster gezeichnet werden. Die Aufgabe des Lernenden besteht darin, die Wörter im Raster zu finden und auszuwählen." + }, + "H5P_InteractiveBook": { + "title": "Interaktives Buch (Interactive Book)", + "summary": "Erstellen Sie kleine Kurse, Bücher und Tests", + "description": "Erstellen Sie kleine Kurse, Bücher oder Tests. Mit Interactive Book können Autoren große Mengen interaktiver Inhalte wie interaktive Videos, Fragen, Kurspräsentationen und mehr auf mehreren Seiten kombinieren. Am Ende finden Sie eine Zusammenfassung, in der die vom Lernenden im gesamten Buch erzielten Ergebnisse zusammengefasst sind.", + "keywords": { "book": "Buch", "course": "Kurs" } + }, + "H5P_KewArCode": { + "title": "KewAr-Code (KewAr Code)", + "summary": "Erstellen Sie QR-Codes für verschiedene Zwecke", + "description": "Mit KewAr Code können Inhaltsdesigner bekannte QR-Codes erstellen. Diese QR-Codes können URLs, aber auch Kontaktinformationen, Ereignisse, geografische Standorte usw. codieren. Personen können sie mit einem QR-Codeleser scannen, um die ausgewählte Aktion auszulösen.", + "keywords": { "QR": "QR" } + }, + "H5P_AdventCalendar": { + "title": "Adventskalender (beta) (Advent Calendar (beta))", + "summary": "Erstellen Sie Überraschungen, die täglich enthüllt werden", + "description": "Erstellen und passen Sie einen schönen Adventskalender an. Sie können dem gesamten Kalender an jeder Tür und als Hintergrund für den Inhalt jeder Tür ein Hintergrundbild hinzufügen. Sie können auch Schneeeffekt und Musik hinzufügen. In jeder Tür können Sie einen Ton, ein Video, einen Text, ein Bild oder einen Link hinzufügen.\r\n\r\nBeachten Sie, dass es für Computer-versierte Benutzer einfach ist, den Inhalt aller Türen sofort anzuzeigen. Wenn Sie an zukünftigen Tagen große Geheimnisse preisgeben möchten, sollten Sie bis zu diesem Tag warten, bevor Sie Ihre großen Geheimnisse in den Kalender aufnehmen.", + "keywords": { + "christmas": "Weihnachten", + "advent": "Advent", + "holidays": "Ferien", + "calendar": "Kalender" + } + } +} diff --git a/packages/h5p-server/assets/translations/hub/en.json b/packages/h5p-server/assets/translations/hub/en.json new file mode 100644 index 000000000..0c814cb38 --- /dev/null +++ b/packages/h5p-server/assets/translations/hub/en.json @@ -0,0 +1,403 @@ +{ + "H5P_Accordion": { + "title": "Accordion (Accordion)", + "summary": "Create vertically stacked expandable items", + "description": "Reduce the amount of text presented to readers by using this responsive accordion. Readers decide which headlines to take a closer look at by expanding the title. Excellent for providing an overview with optional in-depth explanations.", + "keywords": { + "accordion": "accordion", + "collapsible_text": "collapsible text" + } + }, + "H5P_ArithmeticQuiz": { + "title": "Arithmetic Quiz (Arithmetic Quiz)", + "summary": "Create time-based arithmetic quizzes", + "description": "Create arithmetic quizzes consisting of multiple choice questions. As an author, all you have to do is decide the type and length of the quiz. Users keep track of score and time spent when solving the quiz.", + "keywords": { + "math": "math", + "arithmetic_quiz": "arithmetic quiz", + "countdown": "countdown" + } + }, + "H5P_Chart": { + "title": "Chart (Chart)", + "summary": "Quickly generate bar and pie charts", + "description": "Need to present simple statistical data graphically without creating the artwork manually? Chart is your answer.", + "keywords": { + "chart": "chart", + "bar_chart": "bar chart", + "pie_chart": "pie chart", + "graph": "graph" + } + }, + "H5P_Collage": { + "title": "Collage (Collage)", + "summary": "Create a collage of multiple images", + "description": "The Collage tool allows you to organize images into a soothing composition. ", + "keywords": { + "collage": "collage", + "image": "image" + } + }, + "H5P_Column": { + "title": "Column (Column)", + "summary": "Organize H5P content into a column layout", + "description": "Organize your content type into a column layout with H5P Column. Content types that address similar material or share a common theme can now be grouped together to create a coherent learning experience. In addition, authors are free to be creative by combining almost all of the existing H5P content types.", + "keywords": { + "column": "column", + "layout": "layout", + "compound": "compound" + } + }, + "H5P_CoursePresentation": { + "title": "Course Presentation (Course Presentation)", + "summary": "Create a presentation with interactive slides", + "description": "Course presentations consist of slides with multimedia, text, and many different types of interactions like interactive summaries, multiple choice questions and interactive videos. Learners can experience new interactive learning material and test their knowledge and memory in Course Presentations. As always with H5P, content is editable in web browsers, and the Course Presentation activity type includes a WYSIWYG drag and drop based authoring tool. A typical use of the Course Presentation activity is to use a few slides to introduce a subject and follow these with a few more slides in which the user’s knowledge is tested. Course Presentations may however be used in many different ways, including as a presentation tool for use in the classroom, or as a game where the usual navigation is replaced with navigation buttons on top of the slides to let the user make choices and see the consequences of their choices.", + "keywords": { + "course_presentation": "course presentation", + "slides": "slides", + "powerpoint": "powerpoint" + } + }, + "H5P_Dialogcards": { + "title": "Dialog Cards (Dialog Cards)", + "summary": "Create text-based turning cards", + "description": "Dialog cards can be used as a drill to help learners memorize words, expressions or sentences. On the front of the card, there's a hint for a word or expression. By turning the card the learner reveals a corresponding word or expression. Dialog cards can be used in language learning, to present math problems or help learners remember facts such as historical events, formulas or names.", + "keywords": { + "dialog_cards": "dialog cards" + } + }, + "H5P_DocumentationTool": { + "title": "Documentation Tool (Documentation Tool)", + "summary": "Create a form wizard with text export", + "description": "The documentation tool aims to make it easy to create assessment wizards for goal driven activities. It can also be used as a form wizard. While editing, the author can add multiple steps to the wizard. In each step, the author can define which content goes into that step. Content can be plain text, input fields, goal definition and goal assessment. Once published, the end user will be taken through the steps of the wizard. On the last step of the wizard, the user can generate a document with all the input that has been submitted. This document can be downloaded. The Documentation tool is fully responsive and works great on smaller screens as well as on your desktop.", + "keywords": { + "dialog_cards": "dialog cards" + } + }, + "H5P_DragQuestion": { + "title": "Drag and Drop (Drag and Drop)", + "summary": "Create drag and drop tasks with images", + "description": "Drag and drop question enables the learner to associate two or more elements and to make logical connections in a visual way. Create Drag and drop questions using both text and images as draggable alternatives. H5P Drag and drop questions support one-to-one, one-to-many, many-to-one and many-to-many relations between questions and answers. ", + "keywords": { + "drag_and drop": "drag and drop" + } + }, + "H5P_DragText": { + "title": "Drag the Words (Drag the Words)", + "summary": "Create text-based drag and drop tasks", + "description": "Drag the Words allows content designers to create textual expressions with missing pieces of text. The end user drags a missing piece of text to its correct place, to form a complete expression. May be used to check if the user remembers a text she has read, or if she understands something. Helps the user think through a text. It's super easy to create a drag the words task. The editor just writes the text and encloses the words that are to be draggable with asterisk signs like *draggableWord*.", + "keywords": { + "drag": "drag", + "words": "words" + } + }, + "H5P_Blanks": { + "title": "Fill in the Blanks (Fill in the Blanks)", + "summary": "Create a task with missing words in a text", + "description": "Learners fill in the missing words in a text. The learner is shown a solution after filling in all the missing words, or after each word depending on settings. Authors enter text and mark words to be replaced with an asterix. In addition to native and second language learning, Fill in the blanks can be used to test the learner's ability to reproduce facts or produce mathematical inferences.", + "keywords": { + "fill": "fill", + "blanks": "blanks", + "text": "text" + } + }, + "H5P_ImageHotspotQuestion": { + "title": "Find the Hotspot (Find the Hotspot)", + "summary": "Create image hotspots for users to find", + "description": "This content type allows end users to press somewhere on an image and get feedback on whether that was correct or incorrect according to the task description. The author uploads an image and defines various hotspots corresponding to details or sections of the image. Hotspots can either be defined as correct or incorrect, and the author provides appropriate feedback text in both cases. The author can also define a feedback if the end user presses somewhere which is neither defined as a correct nor incorrect hotspot.", + "keywords": { + "find": "find", + "hotspot": "hotspot", + "image": "image" + } + }, + "H5P_GuessTheAnswer": { + "title": "Guess the Answer (Guess the Answer)", + "summary": "Create an image with a question and answer", + "description": "This content type allows authors to upload an image and add a suitable description. End users can guess the answer and press the bar below the image to reveal the correct answer.", + "keywords": { + "guess": "guess", + "answer": "answer" + } + }, + "H5P_IFrameEmbed": { + "title": "Iframe Embedder (Iframe Embedder)", + "summary": "Embed from a url or a set of files", + "description": "The Iframe embedder makes it easy to make an H5P of already existing JavaScript applications.", + "keywords": { + "embed": "embed", + "iframe": "iframe" + } + }, + "H5P_InteractiveVideo": { + "title": "Interactive Video (Interactive Video)", + "summary": "Create videos enriched with interactions", + "description": "Add interactivity to your video with explanations, extra pictures, tables, Fill in the Blank and multiple choice questions. Quiz questions support adaptivity, meaning that you can jump to another part of the video based on the user's input. Interactive summaries can be added at the end of the video. Interactive videos are created and edited using the H5P authoring tool in a standard web browser.", + "keywords": { + "interactive": "interactive", + "video": "video" + } + }, + "H5P_MarkTheWords": { + "title": "Mark the Words (Mark the Words)", + "summary": "Create a task where users highlight words", + "description": "Mark the words allows content designers to create textual expressions with a defined set of correct words. The end user highlights words according to the task description and is given a score. For the editor it is super easy to create a click the words challenge. The editor types in the text and encloses the words that the user is supposed to click, the right answers, in asterix like *correctWord*.", + "keywords": { + "mark": "mark", + "words": "words" + } + }, + "H5P_MemoryGame": { + "title": "Memory Game (Memory Game)", + "summary": "Create the classic image pairing game", + "description": "Create your own memory games and test the memory of your site's users with this simple yet beautiful HTML5 game.", + "keywords": { + "memory": "memory", + "game": "game", + "cards": "cards" + } + }, + "H5P_MultiChoice": { + "title": "Multiple Choice (Multiple Choice)", + "summary": "Create flexible multiple choice questions", + "description": "Multiple Choice questions can be an effective assesment tool. The learner is given immediate performance feedback. The H5P Multiple Choice questions can have a single or multiple correct options per question.", + "keywords": { + "multiple": "multiple", + "choice": "choice", + "quiz": "quiz" + } + }, + "H5P_PersonalityQuiz": { + "title": "Personality Quiz (Personality Quiz)", + "summary": "Create personality quizzes", + "description": "In this content type, the author defines a series of questions with alternatives, where each alternative is matched against one or more personalities. At the end of the quiz, the end user will see which personality matches the best. There are several ways of making this quiz visually appealing, by eg. representing questions, alternatives, and personalities using images.", + "keywords": { + "personality": "personality", + "quiz": "quiz" + } + }, + "H5P_Questionnaire": { + "title": "Questionnaire (Questionnaire)", + "summary": "Create a questionnaire to receive feedback", + "description": "Gain feedback and ask open ended questions in Interactive Videos and other content types with Questionnaire. Questionnaire makes the user's answers available via an xAPI integration. This means that website owners may store the answers in many different ways. Answers may be stored in an LRS, the sites own custom storage or a script can fetch the e-mail address and use it to send the user an e-mail. On H5P.org answers are stored in Google Analytics.", + "keywords": { + "questionnaire": "questionnaire" + } + }, + "H5P_QuestionSet": { + "title": "Quiz (Question Set) (Quiz (Question Set))", + "summary": "Create a sequence of various question types", + "description": "Question Set is your typical quiz content type. It allows the learner to solve a sequence of various question types such as Multichoice, Drag and drop and Fill in the blanks in a Question set. As an author, there are many settings you can use to make it behave just the way you want it to. You may, for instance, customize the Question set with background images and define a pass percentage for the learner. The Question Set also allows you to add videos that are played at the end. One video for success, another if the learner fails the test. This might motivate learners to try again if they fail so that they get to see the success video.", + "keywords": { + "question_set": "question set", + "collection": "collection", + "quiz": "quiz" + } + }, + "H5P_SingleChoiceSet": { + "title": "Single Choice Set (Single Choice Set)", + "summary": "Create questions with one correct answer", + "description": "Single choice set allows content designers to create question sets with one correct answer per question. The end user gets immediate feedback after submitting each answer.", + "keywords": { + "collection": "collection", + "quiz": "quiz", + "choice": "choice" + } + }, + "H5P_Summary": { + "title": "Summary (Summary)", + "summary": "Create tasks with a list of statements", + "description": "Summaries help the learner remember key information in a text, video or presentation, by actively buliding a summary about the topic at hand. When the learner has completed a summary, a complete list of key statements about the topic is shown.", + "keywords": { + "summary": "summary" + } + }, + "H5P_Timeline": { + "title": "Timeline (Timeline)", + "summary": "Create a timeline of events with multimedia", + "description": "This is Timeline.js developed by Knight Lab, packaged as an H5P content type in order to make timelines easily editable, shareable and reuseable. The Timeline content type allows you to place a sequence of events in a chronological order. For each event you may add images and texts. You may also include assets from Twitter, YouTube, Flickr, Vimeo, Google Maps and SoundCloud.", + "keywords": { + "timeline": "timeline", + "slider": "slider" + } + }, + "H5P_TrueFalse": { + "title": "True/False Question (True/False Question)", + "summary": "Create True/False questions", + "description": "True/False Question is a simple and straightforward content type that can work by itself or be inserted into other content types such as Course Presentation. A more complex question can be created by adding an image or a video.", + "keywords": { + "true": "true", + "false": "false" + } + }, + "H5P_ImageHotspots": { + "title": "Image Hotspots (Image Hotspots)", + "summary": "Create an image with multiple info hotspots", + "description": "Image hotspots makes it possible to create an image with interactive hotspots. When the user presses a hotspot, a popup containing a header and text or video is displayed. Using the H5P editor, you may add as many hotspots as you like.", + "keywords": { + "image": "image", + "hotspot": "hotspot" + } + }, + "H5P_ImageMultipleHotspotQuestion": { + "title": "Find Multiple Hotspots (Find Multiple Hotspots)", + "summary": "Create many hotspots for users to find", + "description": "A free HTML5 based question type allowing creatives to create an image based test where the learner is to find the correct spots on an image. Use this content type with the H5P plugin for WordPress, Moodle or Drupal to challenge your users." + }, + "H5P_ImageJuxtaposition": { + "title": "Image Juxtaposition (Image Juxtaposition)", + "summary": "Create interactive images", + "description": "A free HTML5-based image content type that allows users to compare two images interactively. Tell your image stories with H5P and Image Juxtaposition on WordPress, Moodle or Drupal." + }, + "H5P_Audio": { + "title": "Audio (Audio)", + "summary": "Upload an audio recording", + "description": "Upload an audio recording in .mp3, .wav, .ogg or provide the link for an audio recording." + }, + "H5P_AudioRecorder": { + "title": "Audio Recorder (Audio Recorder)", + "summary": "Create an audio recording", + "description": "An HTML5 audio recorder. Record your voice and play back or download a .wav file of your recording. Use the H5P plugin to create the H5P Audio Recorder to your Drupal, Wordpress or Moodle site. ", + "keywords": { + "audio": "audio", + "recorder": "recorder" + } + }, + "H5P_SpeakTheWords": { + "title": "Speak the Words (Speak the Words)", + "summary": "Answer a question using your voice (Chrome only)", + "description": "Speak the Words is only supported in browsers that implements the Web Speech API (Chrome browsers, except on iOS). You need a microphone to answer the question. Ask a question to users and make them answer using their voice. You can choose multiple correct answers. The user will be able to see what his words were interpreted as, and how close it was to the correct answers.", + "keywords": { + "language": "language", + "translation": "translation", + "voice": "voice", + "recognition": "recognition", + "speech": "speech", + "mic": "mic", + "microphone": "microphone" + } + }, + "H5P_Agamotto": { + "title": "Agamotto (Image Blender) (Agamotto (Image Blender))", + "summary": "Present a sequence of images and explanations", + "description": "Present a sequence of images that people are supposed to look at one after the other, e.g. photos of an item that changes over time, schematics or maps that are organized in different layers or images that reveal more and more details.", + "keywords": { + "image": "image", + "images": "images", + "transition": "transition" + } + }, + "H5P_ImageSequencing": { + "title": "Image Sequencing (Image Sequencing)", + "summary": "Place images in the correct order", + "description": "A free HTML5 based image sequencing content type that allows authors to add a sequence of their own images (and optional image description) to the game in a particular order. The order of the images will be randomized and players will have to reorder them based on the task description. ", + "keywords": { + "image": "image", + "sequence": "sequence", + "order": "order" + } + }, + "H5P_Flashcards": { + "title": "Flashcards (Flashcards)", + "summary": "Create stylish and modern flashcards", + "description": "This content type allows authors to create a single flash card or a set of flashcards, where each card has images paired with questions and answers. Learners are required to fill in the text field and then check the correctness of their solution.", + "keywords": { + "cards": "cards", + "animation": "animation" + } + }, + "H5P_SpeakTheWordsSet": { + "title": "Speak the Words Set (Speak the Words Set)", + "summary": "Create a series of questions answered by speech (Chrome only)", + "description": "Speak the Words Set is only supported in browsers that implement the Web Speech API (Chrome browsers, except on ios). You need a microphone to answer the question. Create a set of questions that learners can answer using their voice. you can choose multiple correct answers. The user will be able to see what his words were interpreted as, and how close it was to the correct answers.", + "keywords": { + "language": "language", + "translation": "translation", + "voice": "voice", + "quiz": "quiz", + "set": "set", + "recognition": "recognition", + "mic": "mic", + "microphone": "microphone" + } + }, + "H5P_ImageSlider": { + "title": "Image Slider (Image Slider)", + "summary": "Easily create an Image Slider", + "description": "Present your images in an appealing way with ease. Authors just have to upload images and provide alternative texts for the images. \r\n\r\nThe next two images are always preloaded so switching between images will usually be snappy with no delay for loading the next image.\r\n\r\nImages may be experienced as part of the page or in full-screen mode. When used as part of the page the system will pick a fixed aspect ratio depending on the images being used. Authors may decide to handle aspect ratios differently.", + "keywords": { + "image": "image", + "images": "images", + "slider": "slider", + "carousel": "carousel" + } + }, + "H5P_Essay": { + "title": "Essay (Essay)", + "summary": "Create Essay with instant feedback", + "description": "In this content type, the author defines a set of keywords that represent crucial aspects of a topic. These keywords are matched against a text that students have composed and can be used to immediately provide feedback - either suggesting to revise certain topic details if a keyword is missing or, confirming the student's ideas if the text contains a keyword.\r\n", + "keywords": { + "Essay": "Essay" + } + }, + "H5P_ImagePair": { + "title": "Image Pairing (Image Pairing)", + "summary": "Drag and drop image matching game", + "description": "Image pairing is a simple and effective activity that require learners to match pairs of images. Since it is not required for both images in a pair to be the same, authors are also able to test the understanding of a relation between two different images. ", + "keywords": { + "image_images matching pair": "image images matching pair" + } + }, + "H5P_Dictation": { + "title": "Dictation (Dictation)", + "summary": "Create a dictation with instant feedback", + "description": "You can add audio samples containing a sentence for dictation and enter the correct transcription. Your students can listen to the samples and enter what they have heard in to a text field. Their answers will be evaluated automatically. Several options will allow you to control the exercise's difficulty. You can optionally add a second audio sample for a sentence that could hold a version spoken slowly. You can also set a limit for how often a sample can be played, define if punctuation should be relevant for scoring, and decide whether small mistakes like typing errors should be counted as no mistake, a full mistake, or just a half mistake.", + "keywords": { + "language": "language", + "audio": "audio" + } + }, + "H5P_BranchingScenario": { + "title": "Branching Scenario (beta) (Branching Scenario (beta))", + "summary": "Create dilemmas and self paced learning", + "description": "Branching Scenario allow authors to present the learners with a variety of rich interactive content and choices. The choices the learners make will determine the next content they see. May be used to create dilemmas, serious games, and self-paced learning." + }, + "H5P_ThreeImage": { + "title": "Virtual Tour (360) (Virtual Tour (360))", + "summary": "Create 360 environments with interactions", + "description": "360 (equirectangular) and normal images may be enriched with interactivities like explanations, videos, sounds, and interactive questions. The images create scenes that also may be linked together to give the user an impression of moving between environments or between different viewpoints within the same environment." + }, + "H5P_FindTheWords": { + "title": "Find the words (Find the words)", + "summary": "Grid word search game", + "description": "A free HTML5-based word search activity that allows authors to create a list of words that will be drawn in a grid. The learner's task is to find and select the words in the grid." + }, + "H5P_InteractiveBook": { + "title": "Interactive Book (Interactive Book)", + "summary": "Create small courses, books and tests", + "description": "Create small courses, books, or tests. Interactive Book allows authors to combine large amounts of interactive content like interactive videos, questions, course presentations, and more on multiple pages. There is a summary at the end summing up the scores obtained by the learner throughout the book.", + "keywords": { + "book": "book", + "course": "course" + } + }, + "H5P_KewArCode": { + "title": "KewAr Code (KewAr Code)", + "summary": "Create QR codes for different purposes", + "description": "KewAr Code enables content designers to create well-known QR codes. Those QR codes can encode URLs, but also contact information, events, geo-locations, etc. People can scan them with a QR code reader in order to trigger the chosen action.", + "keywords": { + "QR": "QR" + } + }, + "H5P_AdventCalendar": { + "title": "Advent Calendar (beta) (Advent Calendar (beta))", + "summary": "Create surprises that will be unveiled daily", + "description": "Build and customize a beautiful advent calendar. You may add a background image to the entire calendar, on each door, and as a background on the content inside each door. You may also add snow- effect and music. Inside each door, you may add a sound, video, text, image, or link.\r\n\r\nDo note that it is easy for computer-savvy users to reveal the content of all doors right away. If you plan to reveal big secrets on future days you should wait until that day before adding your big secrets to the calendar.", + "keywords": { + "christmas": "christmas", + "advent": "advent", + "holidays": "holidays", + "calendar": "calendar" + } + } +} diff --git a/packages/h5p-server/scripts/create-hub-base-locale.ts b/packages/h5p-server/scripts/create-hub-base-locale.ts new file mode 100644 index 000000000..72701a7f6 --- /dev/null +++ b/packages/h5p-server/scripts/create-hub-base-locale.ts @@ -0,0 +1,32 @@ +import fsExtra from 'fs-extra'; +import path from 'path'; + +const hubData = fsExtra.readJSONSync( + path.resolve( + path.join( + __dirname, + '../../../test/data/content-type-cache/real-content-types.json' + ) + ) +); + +const reducedHubData = hubData.contentTypes.reduce((prev, ct) => { + prev[ct.id.replace('.', '_')] = { + title: `${ct.title} (${ct.title})`, + summary: ct.summary, + description: ct.description, + keywords: ct.keywords?.reduce((prev, curr) => { + prev[curr.replace(' ', '_')] = curr; + return prev; + }, {}) + }; + return prev; +}, {}); + +fsExtra.writeJSONSync( + path.resolve(path.join(__dirname, '../assets/translations/hub/en.json')), + reducedHubData, + { + spaces: 4 + } +); diff --git a/packages/h5p-server/src/ContentTypeInformationRepository.ts b/packages/h5p-server/src/ContentTypeInformationRepository.ts index 58d52d804..cf5c0c04b 100644 --- a/packages/h5p-server/src/ContentTypeInformationRepository.ts +++ b/packages/h5p-server/src/ContentTypeInformationRepository.ts @@ -14,6 +14,7 @@ import { IHubInfo, IInstalledLibrary, ILibraryInstallResult, + ITranslationFunction, IUser } from './types'; @@ -36,21 +37,35 @@ export default class ContentTypeInformationRepository { * @param contentTypeCache * @param libraryManager * @param config + * @param translationCallback (optional) if passed in, the object will try + * to localize content type information (if a language is passed to the + * `get(...)` method). You can safely leave it out if you don't want to + * localize hub information. */ constructor( private contentTypeCache: ContentTypeCache, private libraryManager: LibraryManager, - private config: IH5PConfig + private config: IH5PConfig, + private translationCallback?: ITranslationFunction ) { log.info(`initialize`); } /** - * Gets the information about available content types with all the extra information as listed in the class description. + * Gets the information about available content types with all the extra + * information as listed in the class description. */ - public async get(user: IUser): Promise { + public async get(user: IUser, language?: string): Promise { log.info(`getting information about available content types`); - const cachedHubInfo = await this.contentTypeCache.get(); + let cachedHubInfo = await this.contentTypeCache.get(); + if ( + this.translationCallback && + language && + language.toLowerCase() !== 'en' && // We don't localize English as the base strings already are in English + !language.toLowerCase().startsWith('en-') + ) { + cachedHubInfo = this.localizeHubInfo(cachedHubInfo, language); + } let hubInfoWithLocalInfo = await this.addUserAndInstallationSpecificInfo( cachedHubInfo, user @@ -294,4 +309,77 @@ export default class ContentTypeInformationRepository { } return library.restricted; } + + /** + * Returns a transformed list of content type information in which the + * visible strings are localized into the desired language. Only works if + * the namespace 'hub' has been initialized and populated by the i18n + * system. + * @param contentTypes + * @param language + * @returns the transformed list of content types + */ + private localizeHubInfo( + contentTypes: IHubContentType[], + language: string + ): IHubContentType[] { + if (!this.translationCallback) { + throw new Error( + 'You need to instantiate ContentTypeInformationRepository with a translationCallback if you want to localize Hub information.' + ); + } + + return contentTypes.map((ct) => { + const cleanMachineName = ct.machineName.replace('.', '_'); + return { + ...ct, + summary: this.tryLocalize( + `${cleanMachineName}.summary`, + ct.summary, + language + ), + description: this.tryLocalize( + `${cleanMachineName}.description`, + ct.description, + language + ), + keywords: ct.keywords.map((kw) => + this.tryLocalize( + `${ct.machineName.replace( + '.', + '_' + )}.keywords.${kw.replace('_', ' ')}`, + kw, + language + ) + ), + title: this.tryLocalize( + `${cleanMachineName}.title`, + ct.title, + language + ) + }; + }); + } + + /** + * Tries localizing the entry of the content type information. If it fails + * (indicated by the fact that the key is part of the localized string), it + * will return the original source string. + * @param key the key to look up the translation in the i18n data + * @param sourceString the original English string received from the Hub + * @param language the desired language + * @returns the localized string or the original English source string + */ + private tryLocalize( + key: string, + sourceString: string, + language: string + ): string { + const localized = this.translationCallback(`hub:${key}`, language); + if (localized.includes(key)) { + return sourceString; + } + return localized; + } } diff --git a/packages/h5p-server/src/H5PAjaxEndpoint.ts b/packages/h5p-server/src/H5PAjaxEndpoint.ts index e3d8f0885..86a65c9a2 100644 --- a/packages/h5p-server/src/H5PAjaxEndpoint.ts +++ b/packages/h5p-server/src/H5PAjaxEndpoint.ts @@ -92,7 +92,7 @@ export default class H5PAjaxEndpoint { 'You must specify a user when calling getAjax(...).' ); } - return this.h5pEditor.getContentTypeCache(user); + return this.h5pEditor.getContentTypeCache(user, language); case 'libraries': if ( machineName === undefined || @@ -650,7 +650,8 @@ export default class H5PAjaxEndpoint { ).length; const contentTypeCache = await this.h5pEditor.getContentTypeCache( - user + user, + language ); return new AjaxSuccessResponse( contentTypeCache, @@ -685,7 +686,8 @@ export default class H5PAjaxEndpoint { ).length; const contentTypes = await this.h5pEditor.getContentTypeCache( - user + user, + language ); return new AjaxSuccessResponse( { diff --git a/packages/h5p-server/src/H5PEditor.ts b/packages/h5p-server/src/H5PEditor.ts index 8821ed7e6..b4fcafc3c 100644 --- a/packages/h5p-server/src/H5PEditor.ts +++ b/packages/h5p-server/src/H5PEditor.ts @@ -113,7 +113,8 @@ export default class H5PEditor { this.contentTypeRepository = new ContentTypeInformationRepository( this.contentTypeCache, this.libraryManager, - config + config, + options?.enableHubLocalization ? translationCallback : undefined ); this.temporaryFileManager = new TemporaryFileManager( temporaryStorage, @@ -305,12 +306,16 @@ export default class H5PEditor { } /** - * Returns the content type cache for a specific user. This includes all available content types for the user (some - * might be restricted) and what the user can do with them (update, install from Hub). + * Returns the content type cache for a specific user. This includes all + * available content types for the user (some might be restricted) and what + * the user can do with them (update, install from Hub). */ - public getContentTypeCache(user: IUser): Promise { + public getContentTypeCache( + user: IUser, + language?: string + ): Promise { log.info(`getting content type cache`); - return this.contentTypeRepository.get(user); + return this.contentTypeRepository.get(user, language); } /** diff --git a/packages/h5p-server/src/types.ts b/packages/h5p-server/src/types.ts index 9dac40ddc..ce5c1974e 100644 --- a/packages/h5p-server/src/types.ts +++ b/packages/h5p-server/src/types.ts @@ -1835,6 +1835,21 @@ export interface IH5PEditorOptions { styles?: string[]; }; }; + /** + * If true, the system will localize the information about content types + * displayed in the H5P Hub. It will use the translationCallback that is + * passed to H5PEditor for this by getting translations from the namespace + * 'hub'. It will try to localize these language strings: + * hub:H5P_Example.description + * hub:H5P_Example.summary + * hub:H5P_Example.keywords.key_word1 + * hub:H5P_Example.keywords.key_word2 + * hub:H5P_Example.keywords. ... + * Note that "H5P_Example" is a transformed version of the machineName of + * the content type main library, in which . is replaced by _. In the key + * words whitespaces are replaced by _. + */ + enableHubLocalization?: boolean; } /** diff --git a/packages/h5p-server/test/ContentTypeInformationRepository.test.ts b/packages/h5p-server/test/ContentTypeInformationRepository.test.ts index e55981925..ae949f5f9 100644 --- a/packages/h5p-server/test/ContentTypeInformationRepository.test.ts +++ b/packages/h5p-server/test/ContentTypeInformationRepository.test.ts @@ -62,6 +62,101 @@ describe('Content type information repository (= connection to H5P Hub)', () => ).contentTypes.length ); }); + + it('localizes information from hub', async () => { + const storage = new InMemoryStorage(); + const config = new H5PConfig(storage); + const libManager = new LibraryManager( + new FileLibraryStorage(`${__dirname}/../../../test/data`) + ); + const cache = new ContentTypeCache(config, storage); + + axiosMock + .onPost(config.hubRegistrationEndpoint) + .reply( + 200, + fsExtra.readJSONSync( + path.resolve( + 'test/data/content-type-cache/registration.json' + ) + ) + ); + axiosMock + .onPost(config.hubContentTypesEndpoint) + .reply( + 200, + fsExtra.readJSONSync( + path.resolve( + 'test/data/content-type-cache/real-content-types.json' + ) + ) + ); + + await cache.updateIfNecessary(); + + const translationSpy = jest.fn( + (name, language) => `_translated_${name.replace('.', '#')}` + ); + const repository = new ContentTypeInformationRepository( + cache, + libManager, + config, + translationSpy + ); + const content = await repository.get(new User(), 'de'); + expect( + content.libraries[0].description.startsWith('_translated_') + ).toBe(true); + expect(translationSpy).toBeCalled(); + }); + + it('leaves information from hub as it is if no locale was found', async () => { + const storage = new InMemoryStorage(); + const config = new H5PConfig(storage); + const libManager = new LibraryManager( + new FileLibraryStorage(`${__dirname}/../../../test/data`) + ); + const cache = new ContentTypeCache(config, storage); + + axiosMock + .onPost(config.hubRegistrationEndpoint) + .reply( + 200, + fsExtra.readJSONSync( + path.resolve( + 'test/data/content-type-cache/registration.json' + ) + ) + ); + axiosMock + .onPost(config.hubContentTypesEndpoint) + .reply( + 200, + fsExtra.readJSONSync( + path.resolve( + 'test/data/content-type-cache/1-content-type.json' + ) + ) + ); + + await cache.updateIfNecessary(); + + const translationSpy = jest.fn((key: string, language) => + key.substr(key.indexOf(':') + 1) + ); + const repository = new ContentTypeInformationRepository( + cache, + libManager, + config, + translationSpy + ); + const content = await repository.get(new User(), 'de'); + expect(content.libraries[0].description).toEqual( + 'The description of content type 1' + ); + expect(translationSpy).toBeCalled(); + }); + it("doesn't fail if update wasn't called", async () => { const storage = new InMemoryStorage(); const config = new H5PConfig(storage);