Wikifunctions wikifunctionswiki https://www.wikifunctions.org/wiki/Wikifunctions:Main_Page MediaWiki 1.48.0-wmf.1 first-letter Media Special Talk User User talk Wikifunctions Wikifunctions talk File File talk MediaWiki MediaWiki talk Template Template talk Help Help talk Category Category talk TimedText TimedText talk Module Module talk Translations Translations talk Event Event talk Wikifunctions:How to create implementations/de 4 9282 333936 333518 2026-10-27T19:21:32Z Ameisenigel 44 Created page with "=== Erstellung handlungsorientierter Fehlermeldungen ===" 333936 wikitext text/x-wiki <languages/> Diese Seite bietet eine detailliertere Anleitung dafür, wie man '''Implementierungen erstellt''' und geht über den Überblick auf {{ll|Wikifunctions:Introduction}} hinaus. <span id="Types_of_Implementations"></span> == Arten von Implementierungen == In Wikifunctions kann eine '''Implementierung''' zwei Hauptformen annehmen: '''Code''' oder '''Komposition'''. Eine Code-Implementierung drückt die Logik der Funktion direkt in einer der verfügbaren Programmiersprachen aus (derzeit Python3 oder JavaScript). Sie ist besonders nützlich, wenn sich das Verhalten der Funktion nicht ohne Weiteres aus bestehenden Wikifunktionen ableiten lässt oder wenn eine präzise Kontrolle über die Datenverarbeitung erforderlich ist. Eine Kompositions-Implementierung definiert die Funktion hingegen vollständig durch die Kombination bestehender Funktionen, ohne dass Code geschrieben werden muss. Kompositionen sind leichter verständlich, wiederverwendbar und lassen sich automatisch in andere Sprachen übersetzen. Sie setzen jedoch voraus, dass geeignete Bausteine ​​bereits vorhanden sind und sind oft weniger leistungsfähig. Prüfe daher zunächst, ob dein Ziel durch Komposition erreicht werden kann. Ist dies nicht möglich oder spielen Leistung oder feingranulare Logik eine Rolle, wähle stattdessen eine Code-Implementierung. Es gibt eine dritte Implementierungsart: '''integrierte Implementierungen'''. Diese werden vom Systemcode ausgeführt und können nicht bearbeitet werden. Höchstwahrscheinlich verfügen alle vordefinierten Funktionen über eine integrierte Implementierung. In solchen Fällen wird beim Öffnen der Implementierungsseite die Meldung ''"{{int|wikilambda-implementation-selector-none}}"'' angezeigt. <span id="Practice_Test-Driven_Development"></span> == Praxis der testgetriebenen Entwicklung == '''Testgetriebene Entwicklung''' oder '''TDD''' ist eine Methode zur Softwareentwicklung, bei der Tests geschrieben werden, bevor der eigentliche Code geschrieben wird. Tests dienen dazu, die Funktionsweise einer Funktion anhand von Beispielen und deren Funktionsweise zu verstehen. In Wikifunctions bietet das Schreiben von Tests als erste Tätigkeit erhebliche Vorteile. Wenn du an einer Implementierung arbeitest, kannst du deinen Code anhand der vorhandenen Tests ausführen, um sicherzustellen, dass er sich wie erwartet verhält. Dadurch lassen sich Fehler frühzeitig erkennen, noch bevor du deine Implementierung veröffentlichst. Tests sind außerdem ein effektives Mittel, um die benötigte Funktion zu beschreiben. Durch das Schreiben von Tests '''kommunizierst du klar das erwartete Verhalten''' und die Community kann bei der Implementierung helfen oder alternative Implementierungen erstellen. Stell dir vor, du möchtest eine Funktion implementieren, die zwei Zeichenketten mit einem Leerzeichen dazwischen verknüpft. Ein einfacher Test dafür könnte so aussehen: <syntaxhighlight lang="prolog"> join_with_space( "Hello", "world" ) => "Hello world" </syntaxhighlight> Sobald du das grundlegende Verhalten definiert hast, ist es wichtig, auch '''an Randfälle zu denken''' — Situationen, in denen die Eingaben so beschaffen sind, dass ein spezielles Verhalten erforderlich sein könnte. Was passiert beispielsweise, wenn deine erste Zeichenkette mit einem Leerzeichen endet oder deine zweite mit einem Leerzeichen beginnt? Soll die Funktion alle vorhandenen Leerzeichen beibehalten und ein weiteres hinzufügen oder ein sauber formatiertes Ergebnis mit nur einem Leerzeichen zwischen den Wörtern zurückgeben? Je nach deinen Anforderungen solltest du einen Test für einen solchen Fall erstellen. Ein Test für diesen Sonderfall könnte beispielsweise einer der folgenden sein — aber nicht beide!: <syntaxhighlight lang="prolog"> join_with_space( "Hello ", " world") => "Hello world" </syntaxhighlight> oder ... <syntaxhighlight lang="prolog"> join_with_space( "Hello ", " world") => "Hello world" </syntaxhighlight> Stell sicher, dass deine Tests alle möglichen Sonderfälle abdecken, und sobald du diese hast, stell sicher, dass sie alle mit der Funktion verbunden sind, indem du sie auswählst und auf "Verbinden" klickst. <span id="Code_implementations"></span> == Code-Implementierungen == [[File:Code implementation.png|thumb|alt=Wikifunctions-Code-Editor, der mit einer Funktionsvorlage initialisiert wurde|Beim Hinzufügen einer neuen Code-Implementierung wird die Funktionsvorlage mit den Funktions- und Argumentnamen initialisiert]] Beim Erstellen einer Implementierung mit Code richtet die Wikifunctions-Benutzeroberfläche einen Code-Editor ein, in dem die ausgewählte Sprache für Syntaxhervorhebung und -validierung aktiviert ist. Sobald die zu implementierende Funktion und die Programmiersprache ausgewählt sind, wird dieser Editor mit der korrekten Funktionsvorlage konfiguriert: '''Entferne oder bearbeite sie nicht!''' Platziere deinen Code innerhalb dieser Funktionssignatur. Falls du Hilfsfunktionen benötigst, kannst du diese einfach in deiner Hauptfunktionsdeklaration deklarieren. <span id="Using_input_types_in_your_code"></span> === Verwendung von Eingabetypen in deinem Code === Die Wikifunctions-Typen {{Z|Z6}} und {{Z|Z40}} können in JavaScript und Python3 wie native Typen verwendet werden. Beispielsweise lässt sich eine Zeichenkette verketten oder ein boolescher Wert direkt in einem logischen Ausdruck verwenden. Um andere Typen in deinen Code-Implementierungen zu verwenden, musst du den jeweiligen Typ genauer untersuchen, herausfinden, ob eine Umwandlung in ein natives Äquivalent existiert, und ihn entsprechend behandeln. Nehmen wir beispielsweise an, wir möchten Python-Code schreiben, der eine Eingabe vom Typ {{Z|Z20420}} verarbeitet. Auf der Seite für diesen Typ sehen wir uns die "Typumwandler in Code" an und suchen nach einem Python-Umwandler. Der Umwandler {{Z|Z20424}} wird auf unsere Datumseingabe angewendet, bevor unser Code ausgeführt wird. Unter "nativer Typ" sehen wir, dass unsere Eingabe ein Python-Dictionary ist, und in der Implementierung können wir die zu erwartenden Schlüssel sehen: <syntaxhighlight lang="python3"> return { 'K1': year, 'K2': month, 'K3': day } </syntaxhighlight> Wenn ein Typ keinen Umwandler besitzt, musst du direkt über seine Schlüssel auf seine Bestandteile zugreifen. Nehmen wir beispielsweise an, deine Funktion <code>Z30000</code> hat einen Eingabeparameter <code>Z30000K1</code> vom Typ {{Z|Z11}}. Dieser Typ besitzt zwei Schlüssel: <code>Z11K1</code> für die Sprache (selbst ein Objekt vom Typ {{Z|Z60}}) und <code>Z11K2</code> für den Zeichenketten-Wert. Das Sprachobjekt hat wiederum einen Schlüssel <code>Z60K1</code> für den Sprachcode. Um also eine Zeichenkette mit dem Sprachcode und dem Text zu erhalten, kannst du folgendes schreiben: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1 ) { // z. B. "de: beliebiger Text" return Z30000K1.Z11K1.Z60K1 + ": " + Z30000K1.Z11K2; } </syntaxhighlight> Für eine Kurzübersicht der verfügbaren Typumwandlungen besuche [[Special:MyLanguage/Wikifunctions:Execution targets#Default type conversion|die Tabelle der Standard-Typumwandlungen]]. <span id="Returning_the_right_outputs"></span> === Rückgabe der richtigen Ausgaben === Ähnlich wie bei der Behandlung von Eingaben müssen auch Ausgaben dem in der Funktionsdefinition angegebenen Typ entsprechen. Einige können wie native Typen behandelt werden; daher wird jede Zeichenketten-Ausgabe in ein Wikifunctions-Objekt {{Z|Z6}} und jeder von deiner Implementierung zurückgegebene native boolesche Wert in ein Wikifunctions-Objekt {{Z|Z40}} umgewandelt. Typen mit "Typumwandlern aus Code" wenden die entsprechende Funktion auf die Ausgabe an, um den benötigten Typ zu erzeugen. Am Beispiel von {{Z|Z20420}} transformiert {{Z|Z20443}} die Ausgabe deiner Implementierung – ein Dictionary mit den Schlüsseln K1, K2 und K3 – in die korrekte ZObjekt-Darstellung. Für Typen, die keine Umwandler aus Code haben, kannst du die Ausgabeobjekte sorgfältig erstellen und zurückgeben. Stell dir beispielsweise vor, unsere Funktion <code>Z30000</code> nimmt zwei Zeichenketten als Eingaben entgegen: Sprachcode und Text, und soll ein Objekt {{Z|Z11}} zurückgeben. In Python kannst du dies mit dem Konstruktor <code>ZObject</code> erreichen: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): lang_object = ZObject( {"Z1K1": "Z9", "Z9K1": "Z60"}, Z60K1 = Z30000K1 ) return ZObject( {"Z1K1": "Z9", "Z9K1": "Z11"}, Z11K1 = lang_object, Z11K2 = Z30000K2 ) </syntaxhighlight> Oder in JavaScript: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1, Z30000K2 ) { const langObject = new ZObject( new Map( [ [ "Z60K1", Z30000K1 ] ] ), { "Z1K1": "Z9", "Z9K1": "Z60" } ); const monolingualKeys = new Map( [ [ "Z11K1", langObject ], [ "Z11K2", Z30000K2 ] ] ); return new ZObject( monolingualKeys, { "Z1K1": "Z9", "Z9K1": "Z11" } ); } </syntaxhighlight> Du kannst mehr über die Klasse <code>ZObject</code> und andere nützliche Konstruktoren auf {{ll|Wikifunctions:Execution_targets#Custom_and_non-built-in_type_conversion}} erfahren. {{phab|T392750}}Stand Mai 2026 kann der Versuch, eine Liste von Listen zurückzugeben, fehlschlagen; daher ist es nicht möglich, solche Funktionen in Code zu implementieren. === Code in Python === In diesem Abschnitt geben wir ein konkretes Beispiel, wie man eine Implementierung in Form von Code in Python erstellt. Angenommen, wir möchten eine Implementierung für eine Funktion erstellen, die zwei Eingabezeichenketten durch Einfügen eines Leerzeichens dazwischen kombiniert und das Ergebnis zurückgibt. Nehmen wir an, die ZID dieser Funktion ist Z30000. Die Implementierung wird über die ZID der Funktion definiert. Das gilt auch für die Argumente der Funktion. Im Fall der Funktion Z30000 mit ihren beiden Argumenten sollte die Funktionsvorlage also so aussehen: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): </syntaxhighlight> Wie bereits erwähnt, wissen wir, dass die Argumente (<code>Z30000K1</code> und <code>Z30000K2</code>) Zeichenketten sind, daher können wir sie genauso behandeln wie native Zeichenketten in Python. Die Funktion sollte außerdem eine Zeichenkette zurückgeben. In unserem Beispiel geben wir einfach die beiden Argumente, getrennt durch ein Leerzeichen, aneinandergereiht zurück: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): return Z30000K1 + " " + Z30000K2 </syntaxhighlight> Da es sich um Python handelt, vergesse nicht, diese Zeile einzurücken. Wenn du unserem Rat gefolgt bist, [[#Practice Test-Driven Development|TDD anzuwenden]], verfügst du bereits über eine Reihe von Tests, von denen du weißt, dass sie funktionieren sollten. In diesem Fall kannst du während der Entwicklung deiner Implementierung auf den kreisförmigen Pfeil im Testbereich klicken und überprüfen, ob deine Implementierung alle Tests besteht. Denke daran, dass die Laufzeit keinen Status hat. Gehe nicht von Werten für globale oder statische Variablen aus. Wenn du weitere Fragen dazu hast, was du in Python tun kannst und was nicht, frage auf [[Wikifunctions:Python implementations]]. === Code in JavaScript === In diesem Abschnitt geben wir ein konkretes Beispiel, wie man eine Implementierung in Form von Code in JavaScript erstellt. Angenommen, wir möchten eine Implementierung für eine Funktion erstellen, die zwei Eingabezeichenketten durch Einfügen eines Leerzeichens dazwischen kombiniert und das Ergebnis zurückgibt. Nehmen wir an, die ZID dieser Funktion ist <code>Z30000</code>. Die Implementierung wird über die ZID der Funktion definiert. Das gilt auch für die Argumente der Funktion. Im Fall der Funktion <code>Z30000</code> mit ihren beiden Argumenten sollte die Funktionsvorlage also so aussehen: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1, Z30000K2 ) { } </syntaxhighlight> Wir wissen, dass die Argumente (<code>Z30000K1</code> und <code>Z30000K2</code>) Zeichenketten sind, daher können wir sie in JavaScript wie native Zeichenketten behandeln. Die Funktion soll außerdem eine Zeichenkette zurückgeben. Um die Funktion zu vervollständigen, kannst du eine Zeile hinzufügen, die die Eingabezeichenketten verkettet, etwa so: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1, Z30000K2 ) { return Z30000K1 + " " + Z30000K2; } </syntaxhighlight> Wenn du Tests wie im Abschnitt [[#Practice Test-Driven Development|TDD]] oben empfohlen hast, klicke auf den kreisförmigen Pfeil im Testbereich und prüfe, ob deine Implementierung alle Tests besteht. Denke daran, dass die Laufzeit keinen Status hat. Gehe nicht von Werten für globale oder statische Variablen aus. Wenn du weitere Fragen dazu hast, was du in JavaScript tun kannst und was nicht, frage auf [[Wikifunctions:JavaScript implementations]]. <span id="Calling_another_Wikifunctions_function"></span> === Aufruf einer anderen Wikifunctions-Funktion === Eine Code-Implementierung kann bestimmte andere Wikifunctions-Funktionen aufrufen, die Ausgabe des Aufrufs empfangen und diese Ausgabe für die weitere Verarbeitung nutzen. Wir bezeichnen solche Aufrufe als Callbacks. Derzeit können aus Sicherheits- und Leistungsgründen nur die folgenden integrierten Wikidata-Abruf- und Suchfunktionen auf diese Weise aufgerufen werden: {{Z|Z6820}}, {{Z|Z6821}}, {{Z|Z6822}}, {{Z|Z6824}}, {{Z|Z6825}}, {{Z|Z6826}}, {{Z|Z6830}} und {{Z|Z6831}}. Diese Funktionalität befindet sich in einem frühen Stadium der Einführung; wir hoffen, in Zukunft Aufrufe für eine größere Bandbreite an Funktionen zu ermöglichen. Betrachten wir eine JavaScript-Implementierung, die einen Callback enthält. Diese Implementierung ruft ein Datenobjekt von Wikidata ab, extrahiert die Bezeichnung dieses Datenobjektes in einer bestimmten Sprache und gibt die Bezeichnung als Zeichenkette zurück. Das abzurufende Datenobjekt wird über das Argument <code>Z400K1</code> angegeben, die Sprache über <code>Z400K2</code>. <syntaxhighlight lang="javascript"> function Z400( Z400K1, Z400K2 ) { const item = Wikifunctions.Call('Z6821', Z400K1); for (const label of item.Z6001K2.Z12K1) { if (label.Z11K1.Z60K1 === Z400K2.Z60K1) { return label.Z11K2; }} return 'NOT FOUND'; } </syntaxhighlight> Ein Callback wird durch den Aufruf von <code>Wikifunctions.Call</code> ausgelöst, wie im Beispiel gezeigt. Das erste Argument für <code>Wikifunctions.Call</code> ist stets die ZID der aufzurufenden Funktion – in diesem Fall {{Z|Z6821}}, welche ein einzelnes Argument entgegennimmt. Darauf folgen, durch Kommas getrennt, die an diese Funktion zu übergebenden Argumente. Hierbei handelt es sich bei dem Argument <code>Z400K1</code> um denselben Wert, der auch an <code>Z400</code> übergeben wurde. Dies ist ein gängiges Muster für die Argumentübergabe an Callbacks, jedoch können die Argumente auch mit dem Konstruktor <code>ZObject</code> (wie oben beschrieben) erstellt oder auf andere Weise bezogen werden. Der Wert von <code>Z400K1</code> wäre eine Instanz von {{Z|Z6091}}, die die QID des abzurufenden Datenobjekts enthält. Zeile 2 des Beispiels ruft <code>Z6821</code> auf, um dieses Datenobjekt von Wikidata abzurufen, und weist das resultierende ZObjekt der Konstante <code>item</code> zu. Der restliche Code durchläuft die Bezeichnungen des Datenobjekts, bis er diejenige findet, die der durch <code>Z400K2</code> angegebenen Sprache entspricht. Für das obige Beispiel haben wir der Einfachheit halber <code>Z6821</code> verwendet. Sofern die Implementierung jedoch nicht das gesamte Objekt benötigt, wird dringend empfohlen, zum Abrufen von Wikidata-Datenobjekten, die sehr groß sein können, <code>Z6820</code> zu verwenden. Obwohl der Aufruf von <code>Z6820</code> etwas komplexer ist, ermöglichen seine Parameter das Abrufen spezifischer Teile eines Wikidata-Datenobjekts. Dies kann die Leistung erheblich steigern und bestimmte Fehler vermeiden, da weniger Netzwerkbandbreite und Verarbeitungszeit erforderlich sind. (<code>Z6820</code> kann auch statt <code>Z6822</code>, <code>Z6824</code>, <code>Z6825</code> und <code>Z6826</code> verwendet werden, um ähnliche Vorteile bei der Bandweitenreduzierung zu erreichen.) Im Folgenden zeigen wir, wie <code>Z6820</code> in <code>Wikifunctions.Call</code> verwendet werden kann, um dasselbe Verhalten wie oben zu erzielen. Beachte, dass wir das zweite an <code>Z6820</code> übergebene Argument, <code>[labelsPart]</code>, nutzen, um festzulegen: “Gib nur die Bezeichnungen des Datenobjekts zurück”, und das dritte Argument, <code>[Z400K2]</code>, verwenden, um festzulegen: “Gib die Bezeichnungen nur in der angegebenen Sprache zurück”. (Dieses Argument würde auch für Aliasse und Beschreibungen gelten, sofern diese im Ergebnis enthalten wären.) <syntaxhighlight lang="javascript"> function Z400( Z400K1, Z400K2 ) { const labelsPart = new ZObject( new Map( [ ['Z6030K1', new ZReference('Z6033')] ] ), {Z1K1: 'Z9', Z9K1: 'Z6030'} ); const entities = Wikifunctions.Call( 'Z6820', [Z400K1], [labelsPart], [Z400K2], []); const item = entities.get(Z400K1.Z6091K1); const labels = item.Z6001K2.Z12K1; for (const label of labels) { if (label.Z11K1.Z60K1 === Z400K2.Z60K1) { return label.Z11K2; }} return 'NOT FOUND'; } </syntaxhighlight> Weitere zu beachtende Hinweise: * Obwohl Code-Implementierungen mittlerweile in der Lage sind, Wikidata-Entitäten abzurufen, wird empfohlen, dass sie keine ''vollständigen'' Entitäten zurückgeben. Dies liegt an den derzeitigen Beschränkungen hinsichtlich der Größe des von einer Code-Implementierung zurückgegebenen Wertes. Um eine vollständige, große Entität abzurufen und zurückzugeben, ist es besser, die Abruffunktion aus einer Komposition heraus aufzurufen. * Es kann nur ein Callback gleichzeitig ausgeführt werden. Aus Sicherheitsgründen ist es nicht möglich, die Nebenläufigkeitsfunktionen von JavaScript oder Python zu nutzen, um mehrere Callbacks parallel auszuführen. ** Beachte jedoch, dass du mithilfe von Z6820 mehrere Entitäten auf einmal abrufen kannst. * Derzeit gibt es eine Obergrenze von 3 MiB für die Größe von Wikidata-Inhalten, die über einen einzelnen Callback an eine Code-Implementierung zurückgegeben werden können. Dieselbe Obergrenze gilt für die Größe des Ergebnisses, das von einer Code-Implementierung zurückgegeben wird. <span id="Compositions"></span> == Kompositionen == Im diesem Abschnitt geben wir ein konkretes Beispiel, wie man eine Implementierung in Form einer Komposition erstellt. Angenommen, wir möchten eine Implementierung für eine Funktion erstellen, die zwei Eingabezeichenketten durch Einfügen eines Leerzeichens dazwischen kombiniert und das Ergebnis zurückgibt. Nehmen wir an, die ZID dieser Funktion ist <code>Z30000</code>. Normalerweise ist es sinnvoll, zunächst darüber nachzudenken, wie man vorhandene Funktionen kombinieren kann, um die gewünschte Ausgabe zu erzielen. Manchmal mag dies trivial sein und du kannst einfach mit dem Zusammenstellen und Funktionen fortfahren, aber in vielen Fällen lohnt es sich, die gewünschte Komposition zu notieren. Beispielsweise könnten wir für die angegebene Funktion die vorhandene Funktion {{Z|Z10000}} verwenden. Diese Funktion nimmt zwei Zeichenketten und erstellt daraus eine Zeichenkette. Aber wir müssen dazwischen ein Leerzeichen einfügen. Wir verbinden also zunächst ein Leerzeichen mit dem Ende der ersten Zeichenkette und verbinden dann die zweite Zeichenfolge mit dem Ergebnis dieser ersten Verbindung. Unsere Komposition könnte also so notiert werden: <syntaxhighlight lang="prolog"> join_strings( join_strings( Z30000K1, " " ), Z30000K2 ) </syntaxhighlight> Es gibt mehrere Möglichkeiten, eine Komposition zu schreiben: Beachte, dass dasselbe auch auf folgende Weise erreicht werden kann: <syntaxhighlight lang="prolog"> join_strings( Z30000K1, join_strings( " ", Z30000K2 ) ) </syntaxhighlight> Eine alternative Implementierung könnte auch die vorhandene Funktion {{Z|Z15175}} verwenden, sodass deine Komposition wie folgt aussehen könnte: <syntaxhighlight lang="prolog"> join_with_separator( Z30000K1, Z30000K2, " " ) </syntaxhighlight> Wie du siehst, gibt es mehrere Möglichkeiten, dies zu erreichen. Nimm dir also Zeit und erkunde die vorhandenen Funktionen, die im {{ll|Wikifunctions:Catalogue}} verfügbar sind. Versuchen wir, das zweite Beispiel zu erstellen, <code>join_strings(Z30000K1, join_strings(" ", Z30000K2))</code>. Um dies zu erstellen: # Um eine Implementierung hinzuzufügen, klicke auf der Funktionsseite in der Tabelle "Implementierungen" auf die Schaltfläche "+". # Stelle sicher, dass die Option "Komposition" unter "Implementierung" ausgewählt ist. # Klicke auf das Symbol "›" oder auf den Link "Funktion auswählen", um die Funktionsdetails anzuzeigen. # Suche unter "Funktion" nach dem Namen der äußersten Funktion, die du verwenden möchtest, in diesem Beispiel "verbinde Zeichenketten". Wähle anschließend die gewünschte Funktion aus der Dropdown-Liste aus. # Du siehst zwei neue Felder, eines für jedes der Argumente, die für die ausgewählte Funktion benötigt werden. # Als erstes Argument möchten wir den ersten Eingabewert für unsere Funktion auswählen: ## Klicke neben "erste Zeichenkette" auf die Schaltfläche "…" und wähle "Argumentreferenz" aus. ## Unter "Schlüssel-ID" kannst du nun die erste Zeichenkette deiner Funktion aus dem Dropdown-Menü auswählen, das alle verfügbaren Eingaben enthält. # Für das zweite Argument möchten wir das Ergebnis eines weiteren Aufrufs von "verbinde Zeichenketten" verwenden: ## Klicke neben "zweite Zeichenkette" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus. ## Suche unter "Funktion" nach der Funktion, die du aufrufen möchtest und wähle sie aus, nämlich "verbinde Zeichenketten". ## Konfiguriere die "erste Zeichenkette" für diesen inneren Funktionsaufruf, indem du einfach ein Leerzeichen in das Textfeld eingibst, und konfiguriere die "zweite Zeichenkette" wie in Schritt 6: Ändere sie mit der Schaltfläche "…" in "Argumentreferenz" und wähle dann das zweite Argument in der Dropdown-Liste aus. Deine Komposition ist nun fertig! Du kannst die Details mithilfe der Pfeiltasten ein- und ausblenden, um dir einen Überblick zu verschaffen. Falls du bereits Tests wie im Abschnitt [[#Practice Test-Driven Development|TDD]] oben empfohlen implementiert hast, klicke im Testbereich auf den kreisförmigen Pfeil und prüfe, ob deine Implementierung die Tests besteht. Sobald deine Komposition die Tests bestanden hat, kannst du sie veröffentlichen. [[File:Composition implementation expanded.png|frame|center|alt=Eine Wikifunctions-Kompositionsimplementierung in ihrer erweiterten Ansicht|Eine Wikifunctions-Kompositionsimplementierung in ihrer erweiterten Ansicht]] [[File:Composition implementation collapsed.png|frame|center|alt=Eine Wikifunctions-Kompositionsimplementierung in ihrer reduzierten Ansicht|Eine Wikifunctions-Kompositionsimplementierung in ihrer reduzierten Ansicht]] <span id="Wikifunctions_error_handling"></span> == Fehlerbehandlung auf Wikifunctions == Als Ersteller einer Wikifunctions-Funktion möchtest du möglicherweise den Benutzer warnen, der deine Funktion aufruft, wenn im Code ein Fehler auftritt oder seine Eingaben bestimmte Kriterien nicht erfüllen. Wenn deine Funktion beispielsweise eine Zeichenkette mit einem Namen erwartet, solltest du prüfen, ob der Name nicht leer ist, und gegebenenfalls eine verständliche Fehlermeldung anzeigen. Hierfür kannst du <code>Wikifunctions.Error()</code> in deinen Code-Implementierungen oder die Funktion {{Z|Z851}} in deinen Kompositionen verwenden. In diesem Abschnitt erfährst du: * Wie man Fehler sowohl aus Code- als auch aus Kompositions-Implementierungen auslöst, * wie man Tests für Fehlerfälle schreibt, und * wie man Fehler abfängt und behandelt, die von Funktionen ausgelöst werden, die man in seinen Kompositionen verwendet. <span id="Throwing_errors_from_code_implementations"></span> === Fehler aus Code-Implementierungen auslösen === Sowohl beim Schreiben von JavaScript- als auch von Python-Code kannst du <code>Wikifunctions.Error()</code> nutzen, um die Ausführung mit einem gewünschten Fehler zu beenden. <code>Wikifunctions.Error()</code> hat zwei Parameter: # Fehlertyp: Eine Zeichenkette, die die ZID des Fehlertyps enthält, den du zurückgeben möchtest. # Fehlerargumente: Eine Liste von Zeichenkettenargumenten zur Erstellung des Fehlers. Gehen wir sie der Reihe nach durch: <span id="Error_type"></span> ==== Fehlertyp ==== Ein Fehlertyp ist ein Objekt, das eine Art von Fehler beschreibt, der im System auftreten kann. Es gibt eine Reihe vordefinierter Fehlertypen, du kannst aber auch eigene Fehlertypen erstellen, die besser zu deinem Anwendungsfall passen. Bei der Verwendung von Fehlern empfiehlt es sich, die verfügbaren Fehlertypen zu durchsuchen, die sich in [[Special:ListObjectsByType/Z50|dieser Liste]] finden. Falls keine passenden Fehler für deinen Fall vorhanden sind, erstelle einen neuen Fehler, indem du zur Erstellungsseite gehst und im Typauswahlfeld "Fehlertyp" auswählst. Lege anschließend die erforderlichen Felder fest: [[File:Error type.png|thumb|alt=Erstellung von Fehlertypen in Wikifunctions|Um einen neuen Fehlertyp (Z50) zu erstellen, bearbeite die Bezeichnung und füge die erforderlichen Schlüssel hinzu.]] * '''Bezeichnung''' – Dies ist der Haupttitel des Fehlers, der eine kurze, aber aussagekräftige Meldung enthalten sollte. Lege die Fehlerbezeichnung im rechten Feld mit dem Titel "Info" fest. * '''Schlüssel''' – Schlüssel enthalten zusätzliche Informationen zur Fehlerursache. Wenn beispielsweise eine Eingabe das falsche Format aufwies, möchtest du den Benutzer möglicherweise über den eingegebenen Inhalt informieren, wenn der Fehler auftritt. Um sie in deinen Implementierungen zu verwenden, müssen Schlüssel vom Zeichenketten sein. Um einen Schlüssel zu erstellen, klicke auf das Symbol "[+]" unterhalb von "Schlüssel", wähle unter "Werttyp" die Option "Zeichenkette" aus und füge eine aussagekräftige Bezeichnung hinzu, beispielsweise "tatsächlich Eingabe". Sobald du alle erforderlichen Schlüssel erstellt hast, kannst du deinen Fehlertyp veröffentlichen und die ID des neu erstellten Objekts speichern. * '''Fehlermeldung''' – Fehlertypen können ein mehrsprachiges Array von Fehlermeldungen enthalten, die mit HTML-Parametern versehen sind. Die Parameter werden als $1, $2 etc. angegeben, wobei die Ziffer dem Schlüssel des Fehlertyps entspricht. Beim Erstellen eines Fehlertyps mit dem Zeichenketten-Schlüssel "aktuelle Eingabe", kann die Fehlermeldung beispielsweise den Platzhalter "$1" verwenden, der zum Zeitpunkt der Fehlerausgabe durch den Wert des Schlüssels "aktuelle Eingabe" ersetzt wird. Um HTML-Meldungen hinzuzufügen, klicke unter "HTML-Fragmente" auf das Symbol "[+]", wähle eine Sprache aus und gib die HTML-Zeichenkette ein. <span id="Error_arguments"></span> ==== Fehlerargumente ==== Fehlerargumente entsprechen den Schlüsseln des Fehlertyps und sollten zusätzliche Informationen zum Verständnis des Fehlers liefern. Fehlerargumente sollten immer Zeichenketten sein. <span id="Using_Wikifunctions.Error()"></span> ==== Verwendung von Wikifunctions.Error() ==== Angenommen, du möchtest einen Fehler auslösen, wenn entweder deine erste oder deine zweite Eingabe leer ist. Du hast den Fehlertyp bereits erstellt und ihm wurde die ZID <code>Z30005</code> zugewiesen. Dein Fehlertyp hat zwei Zeichenketten-Schlüssel: * Eingabeschlüssel: Enthält den Schlüssel der fehlerhaften Eingabe * Eingabewert: Enthält den aktuellen Wert der fehlerhaften Eingabe Um einen Fehler in deiner JavaScript-Implementierung auszulösen, solltest du etwa Folgendes tun: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1, Z30000K2 ) { if ( trim( Z30000K1 ) === '' ) { // Wenn die erste Eingabe leer ist, löse Fehler Z30005 aus // mit zwei Zeichenketten-Argumenten: [ erster Eingabe-Schlüssel, erster Eingabe-Wert ] Wikifunctions.Error( 'Z30005', [ "Z30000K1", Z30000K1 ] ) } if ( trim( Z30000K2 ) === '' ) { // Wenn die zweite Eingabe leer ist, löse Fehler Z30005 aus // mit zwei Zeichenketten-Argumenten: [ zweiter Eingabe-Schlüssel, zweiter Eingabe-Wert ] Wikifunctions.Error( 'Z30005', [ "Z30000K2", Z30000K2 ] ) } return Z30000K1 + " " + Z30000K2; } </syntaxhighlight> Um einen Fehler in deiner Python-Implementierung auszulösen, solltest du etwa Folgendes tun: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): if Z30000K1.strip() == "": # Wenn die erste Eingabe leer ist, löse Fehler Z30005 aus # mit zwei Zeichenketten-Argumenten: [ erster Eingabe-Schlüssel, erster Eingabe-Wert ] Wikifunctions.Error("Z30005", ["Z30000K1", Z30000K1]) if Z30000K2.strip() == "": # Wenn die zweite Eingabe leer ist, löse Fehler Z30005 aus # mit zwei Zeichenketten-Argumenten: [ erster Eingabe-Schlüssel, erster Eingabe-Wert ] Wikifunctions.Error("Z30005", ["Z30000K2", Z30000K2]) return Z30000K1 + " " + Z30000K2 </syntaxhighlight> Denke daran, dass der Aufruf von <code>Wikifunctions.Error()</code> die Ausführung beendet! <span id="Throwing_errors_from_compositions"></span> === Fehler aus Kompositionen auslösen === Wenn du eine Kompositionsimplementierung erstellst, kannst du einen Fehler auslösen, indem du die Spezialfunktion {{Z|Z851}} aufrufst. <span id="Throw_Error_function_(Z851)"></span> ==== Funktion Fehler auslösen (Z851) ==== Die Funktion {{Z|Z851}} ähnelt der Methode <code>Wikifunctions.Error()</code> und benötigt zwei Argumente: * '''Fehlertyp''' – Ein Verweis auf den Fehlertyp, den du auslösen möchtest * '''Fehlerparameter''' – Eine Liste mit den Argumenten zur Erstellung deines Fehlers, die ebenfalls Zeichenketten sein sollten. <span id="Using_Throw_Error"></span> ==== Verwendung von Fehler auslösen ==== Angenommen, du möchtest deine Komposition so ändern, dass sie zuerst prüft, ob die Argumente nicht leer sind, und einen Fehler ausgibt, wenn sie ein leeres Argument findet. Wenn dann keines der Argumente leer ist, wird die ursprüngliche Komposition ausgeführt, die wie folgt aussieht: <syntaxhighlight lang="prolog"> join_with_separator( Z30000K1, Z30000K2, " " ) </syntaxhighlight> Dazu musst du bedingte Pfade erstellen, für die du die Funktion {{Z|Z802}} verwenden kannst. Stell es dir folgendermaßen vor: * Wenn das erste Argument leer ist, soll ein Fehler für das erste Argument ausgelöst werden * Andernfalls wird mit der Überprüfung des zweiten Arguments fortgefahren * Wenn das zweite Argument leer ist, soll ein Fehler für das zweite Argument ausgelöst werden * Andernfalls wird der Erfolgspfad verfolgt und die verbundenen Zeichenketten mit dem Leerzeichen als Trennzeichen zurückgegeben Oder in funktionalem Pseudocode: <syntaxhighlight lang="prolog"> if ( is_empty_string( Z30000K1 ), throw_error( Z30005, [ "Z30000K1", Z30000K1 ] ), if( is_empty_string( Z30000K2 ), throw_error( Z30005, [ "Z30000K2", Z30000K2 ] ), join_with_separator( Z30000K1, Z30000K2, " " ) ) ) </syntaxhighlight> Lass uns das Schritt für Schritt erstellen: # Um eine Implementierung hinzuzufügen, klicke auf der Funktionsseite in der Tabelle "Implementierungen" auf die Schaltfläche "+". # Stelle sicher, dass die Option "Komposition" unter "Implementierung" ausgewählt ist. # Klicke auf das Symbol "›" oder auf den Link "Funktion auswählen", um die Funktionsdetails anzuzeigen. # Suche unter "Funktion" nach der äußersten Funktion, die du verwenden möchtest, in diesem Fall "wenn", und wähle sie aus. # Überprüfe die Gültigkeit des ersten Arguments: ## Klicke neben "Bedingung" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "ist leere Zeichenkette" und wähle sie aus ## Klicke neben "Eingabe" auf die Schaltfläche "…" und wähle "Argumentreferenz" aus ## Wähle unter "Schlüssel-ID" die erste Eingabe aus (z. B. "erste Zeichenkette") ## Du kannst den Funktionsaufruf der "Bedingung" nun bei Bedarf ausblenden, indem du auf den Pfeil nach unten neben "Bedingung" klickst. Es sollte dann etwa Folgendes angezeigt werden: "f(x) ist leere Zeichenkette ( → erste Zeichenkette )" # Fehler auslösen, wenn die Bedingung wahr ist: ## Klicke neben "dann" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "Fehler auslösen" und wähle sie aus ## Suche unter "Fehlertyp" nach deinem Fehlertyp (du kannst die Fehler-ID direkt eingeben, wenn du sie kennst, z. B. Z30005) und wähle ihn aus ## Füge unter "Fehlerparameter" zwei Elemente hinzu, indem du auf die Schaltfläche "+" klickst ## Lege für "Objekt 1" (fehlerhafter Argumentschlüssel) den Typ auf "Zeichenkette" fest und trage die Argumentkennung ein (z. B. "erste Eingabe" oder "Z30000K1") ## Klicke für "Objekt 2" (fehlerhafter Argumentwert) auf die "…" neben "Objekt 2" und wähle "Argumentreferenz" aus ## Wähle unter "Schlüssel-ID" die erste Eingabe aus (z. B. "erste Zeichenkette") ## Du kannst den Funktionsaufruf "dann" nun bei Bedarf ausblenden, indem du auf den Pfeil nach unten neben "dann" klickst. Es sollte dann etwa Folgendes angezeigt werden: "f(x) Fehler auslösen ( ungültiges Format, typisierte Liste ( Objekt, "erste Eingabe", → erste Zeichenkette ) )" # Prüfe das zweite Argument, wenn das erste korrekt war: ## Klicke neben "sonst" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "wenn" und wähle sie aus ## Richte eine "Bedingung" ein, um die Gültigkeit des zweiten Arguments zu überprüfen, indem du das gleiche Verfahren wie in Schritt 5 beschrieben anwendest. ## Richte "dann" so ein, dass beim zweiten Argument ein Fehler ausgelöst wird, indem du das gleiche Verfahren wie in Schritt 6 beschrieben anwendest. # Richte schließlich den Erfolgspfad ein: ## Klicke neben dem verschachtelten "sonst" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der gewünschten Funktion, in diesem Fall "vereinige zwei Zeichenketten mit Trennzeichen", und wähle sie aus ## Klicke neben "erste Zeichenkette" auf die Schaltfläche "…" und setze sie auf "Argumentreferenz", wähle anschließend "erste Zeichenkette" aus ## Klicke neben "zweite Zeichenkette" auf die Schaltfläche "…" und setze sie auf "Argumentreferenz", wähle anschließend "zweite Zeichenkette" aus ## Füge unter "Trennzeichen" ein Leerzeichen in das Textfeld ein Der resultierende Funktionsaufruf sollte folgendermaßen aussehen: [[File:Throw error expanded.png|frame|center|alt=Wikifunctions-Komposition mit der Funktion Fehler auslösen|Wikifunctions-Komposition mit der Funktion Fehler auslösen]] [[File:Throw error collapsed.png|frame|center|alt=Wikifunctions-Komposition mit der Funktion Fehler auslösen in ihrer reduzierten Ansicht|Wikifunctions-Komposition mit der Funktion Fehler auslösen in ihrer reduzierten Ansicht]] <span id="Handling_errors_in_compositions"></span> === Fehlerbehandlung in Kompositionen === Es ist zwar nützlich, Funktionen das Auslösen erwarteter Fehler zu ermöglichen, aber es ist entscheidend, Fehler in den eigenen Kompositionen behandeln zu können, um diese Funktionen sicher verwenden zu können. Angenommen, du möchtest eine neue Funktion "vollständiger Name einer Person" erstellen – wir bezeichnen sie mit der ZID <code>Z30010</code>. Diese Funktion soll den vollständigen Namen einer Person anhand ihres Vor- und Nachnamens zurückgeben. Ist jedoch eines der beiden Felder leer, soll sie stattdessen den Text "Unbekannt" zurückgeben. Du könntest eine Komposition erstellen, indem du unsere Beispielfunktion "verbinde zwei Zeichenketten mit Leerzeichen" oder <code>Z30000</code> verwendest, um den Namen zu generieren. Wenn eine der Eingaben leer ist, weißt du, dass <code>Z30000</code> einen Fehler vom Typ <code>Z30005</code> auslöst. Mithilfe der Funktion {{Z|Z850}} als Wrapper kannst du die Verbindungsoperation ausführen und einen möglichen Fehler abfangen, indem du einfach "Unbekannt" zurückgibst, wenn er auftritt. <span id="Try-Catch_function_(Z850)"></span> ==== Try-Catch-Funktion (Z850) ==== Die Funktion {{Z|Z850}} ist eine integrierte Funktion mit der ZID <code>Z850</code> und benötigt drei Argumente: * '''Funktionsaufruf''' – Der erste Funktionsaufruf, der ausgeführt werden soll. Wenn kein Fehler auftritt, ist die Antwort das Ergebnis dieses Funktionsaufrufs. * '''Fehlertyp''' – Ein Fehlertyp, der abgefangen werden soll, falls er während der Ausführung des ersten Funktionsaufrufs auftritt. * '''Fehlerhandler''' – Ein Funktionsaufruf, der ausgeführt wird, falls der oben genannte Fehler während der Ausführung des ursprünglichen Funktionsaufrufs auftritt. In diesem Fall wird das Ergebnis der Fehlerbehandlung zurückgegeben. <span id="Using_Try-Catch"></span> ==== Verwendung der Try-Catch-Funktion ==== Sobald wir alle Funktionen für unsere Komposition haben, können wir sie folgendermaßen gestalten: <syntaxhighlight lang="prolog"> try_catch( join_with_space( Z30010K1, Z30010K2 ), Z30005, echo( "Unknown" ) ) </syntaxhighlight> Das bedeutet: * Die Funktion "verbinde zwei Zeichenketten mit Leerzeichen" wird mit den beiden Eingaben ausprobiert und wenn alles erfolgreich verläuft, wird das Ergebnis dieser Funktion zurückgegeben * Wenn eine der Eingaben leer ist, löst "verbinde zwei Zeichenketten mit Leerzeichen" einen Fehler vom Typ <code>Z30005</code> aus * Unsere {{Z|Z850}} erkennt dann diesen Fehler und führt die Funktion {{Z|Z801}} aus, die "Unbekannt" zurückgibt Lass uns das Schritt für Schritt erstellen: # Um eine Implementierung hinzuzufügen, klicke auf der Funktionsseite in der Tabelle "Implementierungen" auf die Schaltfläche "+". # Stelle sicher, dass die Option "Komposition" unter "Implementierung" ausgewählt ist. # Klicke auf das Symbol "›" oder auf den Link "Funktion auswählen", um die Funktionsdetails anzuzeigen. # Suche unter "Funktion" nach der äußersten Funktion, die du verwenden möchtest, in diesem Fall "Try-Catch-Funktion", und wähle sie aus. # Richte den Hauptfunktionsaufruf ein: ## Klicke unterhalb des Feldes, in dem die "Try-Catch-Funktion" ausgewählt ist, neben dem Schlüssel "Funktionsaufruf" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "verbinde zwei Zeichenketten mit Leerzeichen" und wähle sie aus ## Klicke neben "erste Zeichenkette" auf die Schaltfläche "…" und wähle "Argumentreferenz" aus, wähle anschließend das Argument "erster Name" aus der Dropdown-Liste aus. ## Klicke neben "zweite Zeichenkette" auf die Schaltfläche "…" und wähle "Argumentreferenz" aus, wähle anschließend das Argument "zweiter Name" aus der Dropdown-Liste aus. # Wähle den abzufangenden Fehler aus: ## Suche unter "Fehlertyp" nach "ungültige Zeichenkette" und wähle es aus – du kannst direkt nach der ZID <code>Z30005</code> suchen # Richte den Funktionsaufruf für den Fehlerhandler ein: ## Klicke neben "Fehlerhandler" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "Echo" und wähle sie aus ## Suche unter "Eingabe" und "Typ" den Typ "Zeichenkette" und wähle ihn aus ## Gib nun unter "Eingabe" im Textfeld "Unbekannt" ein Die resultierende Funktion sollte folgendermaßen aussehen: [[File:Try catch expanded.png|frame|center|alt=Wikifunctions-Komposition mit der Try-Catch-Funktion in ihrer erweiterten Ansicht|Wikifunctions-Komposition mit der Try-Catch-Funktion in ihrer erweiterten Ansicht]] [[File:Try catch collapsed.png|frame|center|alt=Wikifunctions-Komposition mit der Try-Catch-Funktion in ihrer reduzierten Ansicht|Wikifunctions-Komposition mit der Try-Catch-Funktion in ihrer reduzierten Ansicht]] <span id="Testing_your_failure_use_cases"></span> === Testen deiner Fehlerfälle === Wie bereits im Abschnitt über die [[#Practice Test-Driven Development|Anwendung von TDD]] erläutert, ist es wichtig, nicht nur die häufigsten Ausführungspfade, sondern auch mögliche Randfälle zu testen. Ebenso wichtig ist es, das Fehlerverhalten zu prüfen. In diesem Abschnitt stellen wir dir die notwendigen Werkzeuge vor, um zu testen, ob deine Funktion bei bestimmten Eingaben fehlschlägt und ob die Fehlermeldung den Erwartungen entspricht. Dazu benötigst du zwei weitere Systemfunktionen: <span id="Is_error_type_(Z852)"></span> ==== ist Fehlertyp (Z852) ==== Die Funktion {{Z|Z852}} ist eine integrierte Funktion mit der ZID <code>Z852</code> und benötigt zwei Argumente: * '''Fehler''' – Ein {{Z|Z5}}-Objekt, das bei einem fehlgeschlagenen Aufruf ausgelöst werden kann. Eine Fehlerinstanz hat einen Typ und einen Wert. * '''Fehlertyp''' – Ein Verweis auf einen {{Z|Z50}}, der mit dem als erstes Argument übergebenen Fehlertyp verglichen wird. Ist dies der Fall, gibt die Funktion wahr zurück. <span id="Get_error_thrown_by_function_call_(Z853)"></span> ==== Fehler erhalten, ausgelöst durch Funktionsaufruf (Z853) ==== Die Funktion {{Z|Z853}} ist eine integrierte Funktion mit der ZID <code>Z853</code> und benötigt ein Argument: * '''Funktionsaufruf''' – Ein Funktionsaufruf, der entweder einen erfolgreichen Wert beliebigen Typs zurückgibt oder einen Fehler auslöst. Diese Funktion gibt ein {{Z|Z882}} zurück, wobei an erster Stelle ein {{Z|Z40}} und an zweiter Stelle ein {{Z|Z1}} steht: * Wenn der Funktionsaufruf erfolgreich ist und somit keinen Fehler auslöst, enthält das zurückgegebene Paar an erster Stelle falsch und an zweiter Stelle leer. * Wenn der Funktionsaufruf einen Fehler auslöst, enthält das zurückgegebene Paar an erster Stelle wahr und an zweiter Stelle den abgefangenen Fehler. Um diese Funktion in deinen Kompositionen zu verwenden, musst du möglicherweise die zusätzlichen Funktionen verwenden: * {{Z|Z821}} und * {{Z|Z822}} <span id="Testing_errors"></span> ==== Fehler testen ==== Angenommen, unsere Zielfunktion "verbinde zwei Zeichenketten mit Leerzeichen" oder <code>Z30000</code> löst einen Fehler vom Typ <code>Z30005</code> aus, und wir möchten dieses Verhalten testen. Dazu müssen wir Folgendes tun: * Einen fehlgeschlagenen Funktionsaufruf auslösen * Den Fehler mit der Funktion {{Z|Z853}} erhalten * Mit {{Z|Z852}} prüfen, ob der Fehler den richtigen Typ hat Tests haben zwei Felder: * '''Aufruf''' – Ein Funktionsaufruf, der mit den zu testenden Eingaben eine Ausgabe erzeugt. Dieser Aufruf gibt einen Wert zurück. * '''Ergebnisprüfung''' – Ein Funktionsaufruf, der überprüft, ob der vom vorherigen Aufruf zurückgegebene Wert dem erwarteten Wert entspricht. Das erste Argument dieses Funktionsaufrufs wird automatisch mit dem Rückgabewert des ersten Aufrufs belegt. Für eine Schritt-für-Schritt-Anleitung zum Erstellen von Tests siehe {{ll|Wikifunctions:Introduction#Create_tests}}. In unserem Beispiel können wir es so strukturieren — aber das ist nicht die einzige Möglichkeit! Der Aufruf, der ein {{Z|Z5}}-Objekt zurückgibt: <syntaxhighlight lang="prolog"> error = get_second_element_of_typed_list( get_error_thrown_by( join_strings_by_whitespace( "", "not empty" ) ) ) </syntaxhighlight> Und die Ergebnisprüfung, die das {{Z|Z5}}-Objekt als erstes Argument verwendet: <syntaxhighlight lang="prolog"> is_error_type( error, Z30005 ) </syntaxhighlight> Lass uns das Schritt für Schritt tun: # Um einen Test hinzuzufügen, klicke auf der Funktionsseite in der Tabelle "Tests" auf die Schaltfläche "+". Die Felder "Aufruf" und "Ergebnisprüfung" enthalten bereits vordefinierte Funktionen. Um die Fehler zu testen, müssen wir diese jedoch ändern. # Als Erstes richten wir den Aufruf ein: ## Klicke unter "Aufruf" auf die Schaltfläche "›", um den Funktionsaufruf zu erweitern. ## Bearbeite das Feld unter "Funktion" und suche die Funktion "erhalte zweites Element eines typisierten Paars" und wähle sie aus ## Klicke anschließend neben "typisiertes Paar" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "Fehler erhalten, ausgelöst durch Funktionsaufruf" und wähle sie aus ## Klicke neben "Funktionsaufruf" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "verbinde zwei Zeichenketten mit Leerzeichen" (oder nach ZID <code>Z30000</code>) und wähle sie aus ## Lege nun die Eingaben so fest, dass ein Fehler auftritt: Mindestens eine von ihnen muss leer sein. ## Du kannst jetzt deinen "Aufruf" durch erneutes Klicken auf den Pfeil nach unten wieder ausblenden, wenn du möchtest! # Als Nächstes richten wir die Ergebnisprüfung ein: ## Klicke unter "Ergebnisprüfung" auf die Schaltfläche "›", um den Funktionsaufruf zu erweitern. ## Bearbeite das Feld unter "Funktion" und suche die Funktion "ist Fehlertyp" und wähle sie aus ## Du wirst nun nur noch aufgefordert, das zweite Argument zu konfigurieren. Suche unter "Fehlertyp" nach deinem Fehlertyp <code>Z30005</code> und wähle ihn aus. # Und du bist fertig! Du kannst jetzt auf den kreisförmigen Pfeil im Feld "Implementierungen" klicken und solltest grüne Häkchen sehen. Wenn alles geklappt hat, kannst du deinen Test jetzt speichern. Er sollte folgendermaßen aussehen: [[File:Get error expanded.png|frame|center|alt=Testen eines Fehlers mit den Funktionen Fehler erhalten und ist Fehlertyp in ihrer erweiterten Ansicht|Testen eines Fehlers mit den Funktionen Fehler erhalten und ist Fehlertyp in ihrer erweiterten Ansicht]] [[File:Get error collapsed.png|frame|center|alt=Testen eines Fehlers mit den Funktionen Fehler erhalten und ist Fehlertyp in ihrer reduzierten Ansicht|Testen eines Fehlers mit den Funktionen Fehler erhalten und ist Fehlertyp in ihrer reduzierten Ansicht]] <span id="Creating_actionable_error_messages"></span> === Erstellung handlungsorientierter Fehlermeldungen === <div lang="en" dir="ltr" class="mw-content-ltr"> As described above, Error Types have an optional key <code>Z50K3</code> which contains a multilingual list of HTML strings. When rendering information about an error, the messages stored in the error type can help create a clear, precise, informative, translatable and actionable error message. </div> <div lang="en" dir="ltr" class="mw-content-ltr"> For that purpose, error messages can contain parameters like <code>$1</code>, <code>$2</code>, etc., where the digit corresponds to the error type argument and its value in the error instance. These error messages are rendered in Wikifunctions inside the "Details" dialog window after executing a function call. Additionally, these error messages are surfaced in other client interfaces, like Abstract Wikipedia, to provide better guidance to Abstract Content editors. </div> [[File:Wikifunctions actionable error message example in the Details dialog.png|thumb|<span lang="en" dir="ltr" class="mw-content-ltr">The error message is rendered using the HTML message of the error type and the error argument values.</span>]] [[File:Wikifunctions actionable error message example in Abstract Wikipedia.png|thumb|<span lang="en" dir="ltr" class="mw-content-ltr">When available, the HTML error message is rendered in the Abstract Wikipedia preview section.</span>]] <div lang="en" dir="ltr" class="mw-content-ltr"> Let's use a real example to understand the benefits of HTML error messages: </div> <div lang="en" dir="ltr" class="mw-content-ltr"> The function {{Z|Z37847}} returns the first Lexeme reference given a Wikidata Item reference and a language. When there is no Lexeme for this Item-Language combination, it throws an error of type {{Z|Z28248}}, which has three keys: </div> * <span lang="en" dir="ltr" class="mw-content-ltr">'''Z28248K1''' is the input Wikidata item QID</span> * <span lang="en" dir="ltr" class="mw-content-ltr">'''Z28248K2''' is the connecting property, in this case <code>P5137/item for this sense</code></span> * <span lang="en" dir="ltr" class="mw-content-ltr">'''Z28248K3''' is the language code</span> <div lang="en" dir="ltr" class="mw-content-ltr"> When calling this function for a Wikidata lexeme that doesn't exist, the call will throw an error instance like this: </div> <syntaxhighlight lang="json" highlight="10,12"> { "Z1K1": "Z5", "Z5K1": "Z28248", "Z5K2": { "Z1K1": { "Z1K1": "Z7", "Z7K1": "Z885", "Z885K1": "Z28248" }, "Z28248K1": "Q319", "Z28248K2": "P5137", "Z28248K3": "ast" } } </syntaxhighlight> <div lang="en" dir="ltr" class="mw-content-ltr"> While the error type label indicates: <code>No matching lexeme for item in language</code>, a better error message should indicate: </div> * <span lang="en" dir="ltr" class="mw-content-ltr">which is the failing item,</span> * <span lang="en" dir="ltr" class="mw-content-ltr">which is the language missing, and</span> * <span lang="en" dir="ltr" class="mw-content-ltr">what are the possible ways to fix it.</span> <div lang="en" dir="ltr" class="mw-content-ltr"> The error message <code>Z50K3</code> field can provide this functionality. Whenever an Error Type has an error message for the user language (or any of its fallbacks), the error message shown will be rendered by: </div> # <span lang="en" dir="ltr" class="mw-content-ltr">First, replacing the message parameters with the values of the keys. In our example, any <code>$1</code> will be replaced with the value of <code>Z28248K1</code> ("Q319"), <code>$2</code> with "P5137", and <code>$3</code> with "ast",</span> # <span lang="en" dir="ltr" class="mw-content-ltr">Last, sanitizing and rendering the HTML message.</span> <div lang="en" dir="ltr" class="mw-content-ltr"> So a HTML message like: </div> <syntaxhighlight lang="html"> There is no matching lexeme for the item $1 in "$3".<br> <a href="http://wikidata.org/wiki/$1">Edit in Wikidata</a> </syntaxhighlight> <div lang="en" dir="ltr" class="mw-content-ltr"> Will become: </div> : There is no matching lexeme for the item Q319 in "ast" : [[d:Q319|Edit in Wikidata]] <span id="Debugging_your_implementations"></span> == Debuggen deiner Implementierungen == Manchmal läuft etwas schief. Eine Funktion verhält sich möglicherweise anders als erwartet oder ein Wert erscheint merkwürdig. Implementierungen können mitunter sehr komplex sein, und da sie in einer Spielwiesen-Umgebung ausgeführt werden, kann die Fehlersuche extrem schwierig erscheinen. Um das Verständnis der Vorgänge innerhalb eines Funktionsaufrufs zu erleichtern, bietet Wikifunctions einige Debugging-Werkzeuge. Diese Werkzeuge verändern nicht das Ergebnis einer Funktion, sondern fügen den zurückgegebenen Metadaten zusätzliche Informationen hinzu, die du nach dem Ausführen der Funktion einsehen kannst. Du kannst <code>Wikifunctions.Debug()</code> in deinen Code-Implementierungen oder die Funktion {{Z|Z854}} in deinen Kompositionen verwenden. In diesem Abschnitt erfährst du: * Wie man Debug-Meldungen sowohl aus Code- als auch aus Kompositions-Implementierungen hinzufügt, * Wie man die Metadaten manuell oder über die Benutzeroberfläche untersucht, um diese Protokolle einzusehen. <span id="Debugging_your_code_implementations"></span> === Debuggen deiner Code-Implementierungen === Beim Schreiben von Code, sowohl in JavaScript als auch in Python3, kannst du <code>Wikifunctions.Debug()</code> verwenden, um eine Meldung zu deinem Debug-Protokoll hinzuzufügen und die Ausführung fortzusetzen. {{phab|T441028}} <code>Wikifunctions.Debug()</code> hat einen Parameter, der üblicherweise als Zeichenkette erwartet wird. Jedes andere als Parameter übergebene Objekt wird jedoch direkt in eine Zeichenkette umgewandelt. Um zu unseren Code-Implementierungen für unsere Beispielfunktion "verbinde zwei Zeichenketten mit Leerzeichen" Debug-Protokolle hinzuzufügen, können wir dies in JavaScript tun: <syntaxhighlight lang="JavaScript"> function Z30000( Z30000K1, Z30000K2 ) { if ( trim( Z30000K1 ) === '' ) { Wikifunctions.Debug( `first input is empty "${ Z30000K1 }"` ); Wikifunctions.Error( 'Z30005', [ "Z30000K1", Z30000K1 ] ) } if ( trim( Z30000K2 ) === '' ) { Wikifunctions.Debug( `second input is empty "${ Z30000K2 }"` ); Wikifunctions.Error( 'Z30005', [ "Z30000K2", Z30000K2 ] ) } Wikifunctions.Debug( "both inputs are fine" ); return Z30000K1 + " " + Z30000K2; } </syntaxhighlight> Und das Gleiche in deiner Python3-Implementierung: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): if Z30000K1.strip() == "": Wikifunctions.Debug( 'first input is empty "'+Z30000K1+'"' ) Wikifunctions.Error("Z30005", ["Z30000K1", Z30000K1]) if Z30000K2.strip() == "": Wikifunctions.Debug( 'second input is empty "'+Z30000K2+'"' ) Wikifunctions.Error("Z30005", ["Z30000K2", Z30000K2]) Wikifunctions.Debug( 'both inputs are fine' ) return Z30000K1 + " " + Z30000K2 </syntaxhighlight> Auf diese Weise fügen wir deinen Debug-Protokollen in jedem Fall eine Meldung hinzu: * Schlägt der Funktionsaufruf bei der Überprüfung der ersten oder zweiten Eingabe fehl, ist das Ergebnis der Ausführung ein Fehler, enthält aber einen informativen Protokolleintrag darüber, welcher Zweig den Fehler verursacht hat. * Wenn der Funktionsaufruf erfolgreich ist — weil beide Eingaben gültig sind — gibt der Funktionsaufruf die verbundene Zeichenkette zurück, aber die zurückgegebenen Metadaten enthalten auch ein Debug-Protokoll. <span id="Debugging_your_compositions"></span> === Debuggen deiner Kompositionen === Zur Unterstützung des Debuggens von Kompositionen stellt Wikifunctions die integrierte Funktion {{Z|Z854}} bereit. Mit dieser Funktion kannst du Debug-Meldungen an die Ausführung jedes Funktionsaufrufs anhängen, der die endgültige Ausgabe erzeugt. Die während der Auswertung gesammelten Debug-Protokolle werden als Teil der Ausführungsmetadaten unter dem Schlüssel <code>executorDebugLogs</code> zurückgegeben. <span id="Add_debug_log_to_function_call_(Z854)"></span> ==== Debug-Protokoll zu Funktionsaufruf hinzufügen (Z854) ==== Die Funktion {{Z|Z854}} ist eine integrierte Funktion mit der ZID <code>Z854</code> und benötigt zwei Argumente: * '''Funktionsaufruf''' – Jede Komposition, die du ausführen möchtest. * '''Debug-Protokoll''' – Eine Zeichenketten-Meldung, die protokolliert wird, wenn der angegebene Funktionsaufruf ausgewertet wird. Wenn der umschlossene Funktionsaufruf ausgeführt wird, wird die bereitgestellte Meldung zu den Ausführungsprotokollen hinzugefügt. Wird dieser Funktionsaufruf nicht ausgeführt oder ist seine Ausführung nicht Teil der endgültigen Ausgabe, erscheint sein Debug-Protokoll nicht in den Metadaten des Endergebnisses. Diese integrierte Funktion ist besonders nützlich, wenn du beobachten möchtest: * Welcher Zweig einer Bedingung ausgeführt wurde, oder * Die Reihenfolge der Auswertung in einer Komposition. <span id="Using_Add_debug_log_to_function_call"></span> ==== Verwendung von Debug-Protokoll zu Funktionsaufruf hinzufügen ==== Angenommen, du möchtest zu unserer Beispielfunktion "verbinde zwei Zeichenketten mit Leerzeichen" oder <code>Z30000</code> Debug-Protokolle hinzufügen, sodass für die verschiedenen möglichen Ergebnisse unterschiedliche Meldungen angezeigt werden. Du könntest unsere integrierte Debugging-Funktion wie folgt verwenden: <syntaxhighlight lang="prolog"> if ( is_empty_string( Z30000K1 ), add_debug_log( throw_error( Z30005, ... ), 'failed on first input' ) if( is_empty_string( Z30000K2 ), add_debug_log( throw_error( Z30005, ... ), 'failed on second input' ), add_debug_log( join_with_separator( Z30000K1, Z30000K2, " " ), 'both inputs are ok!' ) ) ) </syntaxhighlight> Dies bewirkt Folgendes: * Wird die Funktion mit einer leeren ersten Eingabe aufgerufen, gibt sie eine Fehlermeldung zurück und die Metadaten enthalten einen Eintrag <code>executorDebugLogs</code> mit dem Protokoll-Eintrag "Fehler bei erster Eingabe". * Wird der Aufruf mit einer leeren zweiten Eingabe aufgerufen, schlägt der Aufruf ebenfalls fehl, die protokollierte Meldung lautet jedoch "Fehler bei zweiter Eingabe". * Bei Aufruf mit gültigen Eingaben gibt die Funktion eine erfolgreiche Antwort zurück und zusätzlich enthalten die Metadaten im Schlüssel <code>executorDebugLogs</code> "Beide Eingaben sind in Ordnung". So würde diese Komposition aussehen: [[File:Add debug log expanded.png|frame|center|alt=Implementierung der Komposition mit Debug-Protokoll hinzufügen, um alle möglichen Ausführungspfade zu protokollieren|Implementierung der Komposition mit Debug-Protokoll hinzufügen, um alle möglichen Ausführungspfade zu protokollieren]] <span id="Accessing_execution_debug_logs"></span> === Zugriff auf Ausführungs-Debug-Protokolle === Unabhängig davon, ob deine Ausführungsprotokolle über <code>Wikifunctions.Debug()</code> oder die integrierte Funktion {{Z|Z854}} hinzugefügt werden, werden sie als Teil der Antwort-Metadaten zurückgegeben. Um die Protokolle zu sehen, klicke nach dem Ausführen deiner Funktion auf die Schaltfläche "Details", die unten im Abschnitt "Ergebnis" erscheint. Die Fehler- und Debug-Informationen werden oben im Dialogfeld "Details" angezeigt. Dies ist das Ergebnis, das du sehen würdest, wenn du die Komposition aus unserem vorherigen Beispiel mit gültigen und ungültigen Eingaben ausführst: {| class="wikitable" | [[File:Execution logs success.png|frameless|center|alt=Funktions-Metadatendialog für eine erfolgreiche Ausführung mit Debug-Protokollen]] | [[File:Execution logs failure.png|frameless|center|alt=Funktions-Metadatendialog für eine fehlgeschlagene Ausführung mit Debug-Protokollen]] |- | Funktions-Metadatendialog für eine erfolgreiche Ausführung: zeigt keine Fehler an, sondern das Protokoll der erfolgreichen Ausführung: ''"Beide Eingaben sind in Ordnung!"'' | Funktions-Metadatendialog für eine fehlgeschlagene Ausführung: zeigt die Fehlerinformationen und das zusätzliche Ausführungsprotokoll für den ersten Fehlerzweig an: ''"Fehler bei erster Eingabe"'' |} [[Category:How to create implementations| {{#translation:}}]] escne8r5kyux46b7q9cm8b0u0fj0phc 333938 333936 2026-10-27T19:25:04Z Ameisenigel 44 Created page with "Wie oben beschrieben, verfügen Fehlertypen über einen optionalen Schlüssel $1, der eine mehrsprachige Liste von HTML-Zeichenketten enthält. Bei der Darstellung von Informationen zu einem Fehler können die im Fehlertyp hinterlegten Meldungen dazu beitragen, eine klare, präzise, ​​informative, übersetzbare und handlungsorientierte Fehlermeldung zu erstellen." 333938 wikitext text/x-wiki <languages/> Diese Seite bietet eine detailliertere Anleitung dafür, wie man '''Implementierungen erstellt''' und geht über den Überblick auf {{ll|Wikifunctions:Introduction}} hinaus. <span id="Types_of_Implementations"></span> == Arten von Implementierungen == In Wikifunctions kann eine '''Implementierung''' zwei Hauptformen annehmen: '''Code''' oder '''Komposition'''. Eine Code-Implementierung drückt die Logik der Funktion direkt in einer der verfügbaren Programmiersprachen aus (derzeit Python3 oder JavaScript). Sie ist besonders nützlich, wenn sich das Verhalten der Funktion nicht ohne Weiteres aus bestehenden Wikifunktionen ableiten lässt oder wenn eine präzise Kontrolle über die Datenverarbeitung erforderlich ist. Eine Kompositions-Implementierung definiert die Funktion hingegen vollständig durch die Kombination bestehender Funktionen, ohne dass Code geschrieben werden muss. Kompositionen sind leichter verständlich, wiederverwendbar und lassen sich automatisch in andere Sprachen übersetzen. Sie setzen jedoch voraus, dass geeignete Bausteine ​​bereits vorhanden sind und sind oft weniger leistungsfähig. Prüfe daher zunächst, ob dein Ziel durch Komposition erreicht werden kann. Ist dies nicht möglich oder spielen Leistung oder feingranulare Logik eine Rolle, wähle stattdessen eine Code-Implementierung. Es gibt eine dritte Implementierungsart: '''integrierte Implementierungen'''. Diese werden vom Systemcode ausgeführt und können nicht bearbeitet werden. Höchstwahrscheinlich verfügen alle vordefinierten Funktionen über eine integrierte Implementierung. In solchen Fällen wird beim Öffnen der Implementierungsseite die Meldung ''"{{int|wikilambda-implementation-selector-none}}"'' angezeigt. <span id="Practice_Test-Driven_Development"></span> == Praxis der testgetriebenen Entwicklung == '''Testgetriebene Entwicklung''' oder '''TDD''' ist eine Methode zur Softwareentwicklung, bei der Tests geschrieben werden, bevor der eigentliche Code geschrieben wird. Tests dienen dazu, die Funktionsweise einer Funktion anhand von Beispielen und deren Funktionsweise zu verstehen. In Wikifunctions bietet das Schreiben von Tests als erste Tätigkeit erhebliche Vorteile. Wenn du an einer Implementierung arbeitest, kannst du deinen Code anhand der vorhandenen Tests ausführen, um sicherzustellen, dass er sich wie erwartet verhält. Dadurch lassen sich Fehler frühzeitig erkennen, noch bevor du deine Implementierung veröffentlichst. Tests sind außerdem ein effektives Mittel, um die benötigte Funktion zu beschreiben. Durch das Schreiben von Tests '''kommunizierst du klar das erwartete Verhalten''' und die Community kann bei der Implementierung helfen oder alternative Implementierungen erstellen. Stell dir vor, du möchtest eine Funktion implementieren, die zwei Zeichenketten mit einem Leerzeichen dazwischen verknüpft. Ein einfacher Test dafür könnte so aussehen: <syntaxhighlight lang="prolog"> join_with_space( "Hello", "world" ) => "Hello world" </syntaxhighlight> Sobald du das grundlegende Verhalten definiert hast, ist es wichtig, auch '''an Randfälle zu denken''' — Situationen, in denen die Eingaben so beschaffen sind, dass ein spezielles Verhalten erforderlich sein könnte. Was passiert beispielsweise, wenn deine erste Zeichenkette mit einem Leerzeichen endet oder deine zweite mit einem Leerzeichen beginnt? Soll die Funktion alle vorhandenen Leerzeichen beibehalten und ein weiteres hinzufügen oder ein sauber formatiertes Ergebnis mit nur einem Leerzeichen zwischen den Wörtern zurückgeben? Je nach deinen Anforderungen solltest du einen Test für einen solchen Fall erstellen. Ein Test für diesen Sonderfall könnte beispielsweise einer der folgenden sein — aber nicht beide!: <syntaxhighlight lang="prolog"> join_with_space( "Hello ", " world") => "Hello world" </syntaxhighlight> oder ... <syntaxhighlight lang="prolog"> join_with_space( "Hello ", " world") => "Hello world" </syntaxhighlight> Stell sicher, dass deine Tests alle möglichen Sonderfälle abdecken, und sobald du diese hast, stell sicher, dass sie alle mit der Funktion verbunden sind, indem du sie auswählst und auf "Verbinden" klickst. <span id="Code_implementations"></span> == Code-Implementierungen == [[File:Code implementation.png|thumb|alt=Wikifunctions-Code-Editor, der mit einer Funktionsvorlage initialisiert wurde|Beim Hinzufügen einer neuen Code-Implementierung wird die Funktionsvorlage mit den Funktions- und Argumentnamen initialisiert]] Beim Erstellen einer Implementierung mit Code richtet die Wikifunctions-Benutzeroberfläche einen Code-Editor ein, in dem die ausgewählte Sprache für Syntaxhervorhebung und -validierung aktiviert ist. Sobald die zu implementierende Funktion und die Programmiersprache ausgewählt sind, wird dieser Editor mit der korrekten Funktionsvorlage konfiguriert: '''Entferne oder bearbeite sie nicht!''' Platziere deinen Code innerhalb dieser Funktionssignatur. Falls du Hilfsfunktionen benötigst, kannst du diese einfach in deiner Hauptfunktionsdeklaration deklarieren. <span id="Using_input_types_in_your_code"></span> === Verwendung von Eingabetypen in deinem Code === Die Wikifunctions-Typen {{Z|Z6}} und {{Z|Z40}} können in JavaScript und Python3 wie native Typen verwendet werden. Beispielsweise lässt sich eine Zeichenkette verketten oder ein boolescher Wert direkt in einem logischen Ausdruck verwenden. Um andere Typen in deinen Code-Implementierungen zu verwenden, musst du den jeweiligen Typ genauer untersuchen, herausfinden, ob eine Umwandlung in ein natives Äquivalent existiert, und ihn entsprechend behandeln. Nehmen wir beispielsweise an, wir möchten Python-Code schreiben, der eine Eingabe vom Typ {{Z|Z20420}} verarbeitet. Auf der Seite für diesen Typ sehen wir uns die "Typumwandler in Code" an und suchen nach einem Python-Umwandler. Der Umwandler {{Z|Z20424}} wird auf unsere Datumseingabe angewendet, bevor unser Code ausgeführt wird. Unter "nativer Typ" sehen wir, dass unsere Eingabe ein Python-Dictionary ist, und in der Implementierung können wir die zu erwartenden Schlüssel sehen: <syntaxhighlight lang="python3"> return { 'K1': year, 'K2': month, 'K3': day } </syntaxhighlight> Wenn ein Typ keinen Umwandler besitzt, musst du direkt über seine Schlüssel auf seine Bestandteile zugreifen. Nehmen wir beispielsweise an, deine Funktion <code>Z30000</code> hat einen Eingabeparameter <code>Z30000K1</code> vom Typ {{Z|Z11}}. Dieser Typ besitzt zwei Schlüssel: <code>Z11K1</code> für die Sprache (selbst ein Objekt vom Typ {{Z|Z60}}) und <code>Z11K2</code> für den Zeichenketten-Wert. Das Sprachobjekt hat wiederum einen Schlüssel <code>Z60K1</code> für den Sprachcode. Um also eine Zeichenkette mit dem Sprachcode und dem Text zu erhalten, kannst du folgendes schreiben: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1 ) { // z. B. "de: beliebiger Text" return Z30000K1.Z11K1.Z60K1 + ": " + Z30000K1.Z11K2; } </syntaxhighlight> Für eine Kurzübersicht der verfügbaren Typumwandlungen besuche [[Special:MyLanguage/Wikifunctions:Execution targets#Default type conversion|die Tabelle der Standard-Typumwandlungen]]. <span id="Returning_the_right_outputs"></span> === Rückgabe der richtigen Ausgaben === Ähnlich wie bei der Behandlung von Eingaben müssen auch Ausgaben dem in der Funktionsdefinition angegebenen Typ entsprechen. Einige können wie native Typen behandelt werden; daher wird jede Zeichenketten-Ausgabe in ein Wikifunctions-Objekt {{Z|Z6}} und jeder von deiner Implementierung zurückgegebene native boolesche Wert in ein Wikifunctions-Objekt {{Z|Z40}} umgewandelt. Typen mit "Typumwandlern aus Code" wenden die entsprechende Funktion auf die Ausgabe an, um den benötigten Typ zu erzeugen. Am Beispiel von {{Z|Z20420}} transformiert {{Z|Z20443}} die Ausgabe deiner Implementierung – ein Dictionary mit den Schlüsseln K1, K2 und K3 – in die korrekte ZObjekt-Darstellung. Für Typen, die keine Umwandler aus Code haben, kannst du die Ausgabeobjekte sorgfältig erstellen und zurückgeben. Stell dir beispielsweise vor, unsere Funktion <code>Z30000</code> nimmt zwei Zeichenketten als Eingaben entgegen: Sprachcode und Text, und soll ein Objekt {{Z|Z11}} zurückgeben. In Python kannst du dies mit dem Konstruktor <code>ZObject</code> erreichen: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): lang_object = ZObject( {"Z1K1": "Z9", "Z9K1": "Z60"}, Z60K1 = Z30000K1 ) return ZObject( {"Z1K1": "Z9", "Z9K1": "Z11"}, Z11K1 = lang_object, Z11K2 = Z30000K2 ) </syntaxhighlight> Oder in JavaScript: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1, Z30000K2 ) { const langObject = new ZObject( new Map( [ [ "Z60K1", Z30000K1 ] ] ), { "Z1K1": "Z9", "Z9K1": "Z60" } ); const monolingualKeys = new Map( [ [ "Z11K1", langObject ], [ "Z11K2", Z30000K2 ] ] ); return new ZObject( monolingualKeys, { "Z1K1": "Z9", "Z9K1": "Z11" } ); } </syntaxhighlight> Du kannst mehr über die Klasse <code>ZObject</code> und andere nützliche Konstruktoren auf {{ll|Wikifunctions:Execution_targets#Custom_and_non-built-in_type_conversion}} erfahren. {{phab|T392750}}Stand Mai 2026 kann der Versuch, eine Liste von Listen zurückzugeben, fehlschlagen; daher ist es nicht möglich, solche Funktionen in Code zu implementieren. === Code in Python === In diesem Abschnitt geben wir ein konkretes Beispiel, wie man eine Implementierung in Form von Code in Python erstellt. Angenommen, wir möchten eine Implementierung für eine Funktion erstellen, die zwei Eingabezeichenketten durch Einfügen eines Leerzeichens dazwischen kombiniert und das Ergebnis zurückgibt. Nehmen wir an, die ZID dieser Funktion ist Z30000. Die Implementierung wird über die ZID der Funktion definiert. Das gilt auch für die Argumente der Funktion. Im Fall der Funktion Z30000 mit ihren beiden Argumenten sollte die Funktionsvorlage also so aussehen: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): </syntaxhighlight> Wie bereits erwähnt, wissen wir, dass die Argumente (<code>Z30000K1</code> und <code>Z30000K2</code>) Zeichenketten sind, daher können wir sie genauso behandeln wie native Zeichenketten in Python. Die Funktion sollte außerdem eine Zeichenkette zurückgeben. In unserem Beispiel geben wir einfach die beiden Argumente, getrennt durch ein Leerzeichen, aneinandergereiht zurück: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): return Z30000K1 + " " + Z30000K2 </syntaxhighlight> Da es sich um Python handelt, vergesse nicht, diese Zeile einzurücken. Wenn du unserem Rat gefolgt bist, [[#Practice Test-Driven Development|TDD anzuwenden]], verfügst du bereits über eine Reihe von Tests, von denen du weißt, dass sie funktionieren sollten. In diesem Fall kannst du während der Entwicklung deiner Implementierung auf den kreisförmigen Pfeil im Testbereich klicken und überprüfen, ob deine Implementierung alle Tests besteht. Denke daran, dass die Laufzeit keinen Status hat. Gehe nicht von Werten für globale oder statische Variablen aus. Wenn du weitere Fragen dazu hast, was du in Python tun kannst und was nicht, frage auf [[Wikifunctions:Python implementations]]. === Code in JavaScript === In diesem Abschnitt geben wir ein konkretes Beispiel, wie man eine Implementierung in Form von Code in JavaScript erstellt. Angenommen, wir möchten eine Implementierung für eine Funktion erstellen, die zwei Eingabezeichenketten durch Einfügen eines Leerzeichens dazwischen kombiniert und das Ergebnis zurückgibt. Nehmen wir an, die ZID dieser Funktion ist <code>Z30000</code>. Die Implementierung wird über die ZID der Funktion definiert. Das gilt auch für die Argumente der Funktion. Im Fall der Funktion <code>Z30000</code> mit ihren beiden Argumenten sollte die Funktionsvorlage also so aussehen: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1, Z30000K2 ) { } </syntaxhighlight> Wir wissen, dass die Argumente (<code>Z30000K1</code> und <code>Z30000K2</code>) Zeichenketten sind, daher können wir sie in JavaScript wie native Zeichenketten behandeln. Die Funktion soll außerdem eine Zeichenkette zurückgeben. Um die Funktion zu vervollständigen, kannst du eine Zeile hinzufügen, die die Eingabezeichenketten verkettet, etwa so: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1, Z30000K2 ) { return Z30000K1 + " " + Z30000K2; } </syntaxhighlight> Wenn du Tests wie im Abschnitt [[#Practice Test-Driven Development|TDD]] oben empfohlen hast, klicke auf den kreisförmigen Pfeil im Testbereich und prüfe, ob deine Implementierung alle Tests besteht. Denke daran, dass die Laufzeit keinen Status hat. Gehe nicht von Werten für globale oder statische Variablen aus. Wenn du weitere Fragen dazu hast, was du in JavaScript tun kannst und was nicht, frage auf [[Wikifunctions:JavaScript implementations]]. <span id="Calling_another_Wikifunctions_function"></span> === Aufruf einer anderen Wikifunctions-Funktion === Eine Code-Implementierung kann bestimmte andere Wikifunctions-Funktionen aufrufen, die Ausgabe des Aufrufs empfangen und diese Ausgabe für die weitere Verarbeitung nutzen. Wir bezeichnen solche Aufrufe als Callbacks. Derzeit können aus Sicherheits- und Leistungsgründen nur die folgenden integrierten Wikidata-Abruf- und Suchfunktionen auf diese Weise aufgerufen werden: {{Z|Z6820}}, {{Z|Z6821}}, {{Z|Z6822}}, {{Z|Z6824}}, {{Z|Z6825}}, {{Z|Z6826}}, {{Z|Z6830}} und {{Z|Z6831}}. Diese Funktionalität befindet sich in einem frühen Stadium der Einführung; wir hoffen, in Zukunft Aufrufe für eine größere Bandbreite an Funktionen zu ermöglichen. Betrachten wir eine JavaScript-Implementierung, die einen Callback enthält. Diese Implementierung ruft ein Datenobjekt von Wikidata ab, extrahiert die Bezeichnung dieses Datenobjektes in einer bestimmten Sprache und gibt die Bezeichnung als Zeichenkette zurück. Das abzurufende Datenobjekt wird über das Argument <code>Z400K1</code> angegeben, die Sprache über <code>Z400K2</code>. <syntaxhighlight lang="javascript"> function Z400( Z400K1, Z400K2 ) { const item = Wikifunctions.Call('Z6821', Z400K1); for (const label of item.Z6001K2.Z12K1) { if (label.Z11K1.Z60K1 === Z400K2.Z60K1) { return label.Z11K2; }} return 'NOT FOUND'; } </syntaxhighlight> Ein Callback wird durch den Aufruf von <code>Wikifunctions.Call</code> ausgelöst, wie im Beispiel gezeigt. Das erste Argument für <code>Wikifunctions.Call</code> ist stets die ZID der aufzurufenden Funktion – in diesem Fall {{Z|Z6821}}, welche ein einzelnes Argument entgegennimmt. Darauf folgen, durch Kommas getrennt, die an diese Funktion zu übergebenden Argumente. Hierbei handelt es sich bei dem Argument <code>Z400K1</code> um denselben Wert, der auch an <code>Z400</code> übergeben wurde. Dies ist ein gängiges Muster für die Argumentübergabe an Callbacks, jedoch können die Argumente auch mit dem Konstruktor <code>ZObject</code> (wie oben beschrieben) erstellt oder auf andere Weise bezogen werden. Der Wert von <code>Z400K1</code> wäre eine Instanz von {{Z|Z6091}}, die die QID des abzurufenden Datenobjekts enthält. Zeile 2 des Beispiels ruft <code>Z6821</code> auf, um dieses Datenobjekt von Wikidata abzurufen, und weist das resultierende ZObjekt der Konstante <code>item</code> zu. Der restliche Code durchläuft die Bezeichnungen des Datenobjekts, bis er diejenige findet, die der durch <code>Z400K2</code> angegebenen Sprache entspricht. Für das obige Beispiel haben wir der Einfachheit halber <code>Z6821</code> verwendet. Sofern die Implementierung jedoch nicht das gesamte Objekt benötigt, wird dringend empfohlen, zum Abrufen von Wikidata-Datenobjekten, die sehr groß sein können, <code>Z6820</code> zu verwenden. Obwohl der Aufruf von <code>Z6820</code> etwas komplexer ist, ermöglichen seine Parameter das Abrufen spezifischer Teile eines Wikidata-Datenobjekts. Dies kann die Leistung erheblich steigern und bestimmte Fehler vermeiden, da weniger Netzwerkbandbreite und Verarbeitungszeit erforderlich sind. (<code>Z6820</code> kann auch statt <code>Z6822</code>, <code>Z6824</code>, <code>Z6825</code> und <code>Z6826</code> verwendet werden, um ähnliche Vorteile bei der Bandweitenreduzierung zu erreichen.) Im Folgenden zeigen wir, wie <code>Z6820</code> in <code>Wikifunctions.Call</code> verwendet werden kann, um dasselbe Verhalten wie oben zu erzielen. Beachte, dass wir das zweite an <code>Z6820</code> übergebene Argument, <code>[labelsPart]</code>, nutzen, um festzulegen: “Gib nur die Bezeichnungen des Datenobjekts zurück”, und das dritte Argument, <code>[Z400K2]</code>, verwenden, um festzulegen: “Gib die Bezeichnungen nur in der angegebenen Sprache zurück”. (Dieses Argument würde auch für Aliasse und Beschreibungen gelten, sofern diese im Ergebnis enthalten wären.) <syntaxhighlight lang="javascript"> function Z400( Z400K1, Z400K2 ) { const labelsPart = new ZObject( new Map( [ ['Z6030K1', new ZReference('Z6033')] ] ), {Z1K1: 'Z9', Z9K1: 'Z6030'} ); const entities = Wikifunctions.Call( 'Z6820', [Z400K1], [labelsPart], [Z400K2], []); const item = entities.get(Z400K1.Z6091K1); const labels = item.Z6001K2.Z12K1; for (const label of labels) { if (label.Z11K1.Z60K1 === Z400K2.Z60K1) { return label.Z11K2; }} return 'NOT FOUND'; } </syntaxhighlight> Weitere zu beachtende Hinweise: * Obwohl Code-Implementierungen mittlerweile in der Lage sind, Wikidata-Entitäten abzurufen, wird empfohlen, dass sie keine ''vollständigen'' Entitäten zurückgeben. Dies liegt an den derzeitigen Beschränkungen hinsichtlich der Größe des von einer Code-Implementierung zurückgegebenen Wertes. Um eine vollständige, große Entität abzurufen und zurückzugeben, ist es besser, die Abruffunktion aus einer Komposition heraus aufzurufen. * Es kann nur ein Callback gleichzeitig ausgeführt werden. Aus Sicherheitsgründen ist es nicht möglich, die Nebenläufigkeitsfunktionen von JavaScript oder Python zu nutzen, um mehrere Callbacks parallel auszuführen. ** Beachte jedoch, dass du mithilfe von Z6820 mehrere Entitäten auf einmal abrufen kannst. * Derzeit gibt es eine Obergrenze von 3 MiB für die Größe von Wikidata-Inhalten, die über einen einzelnen Callback an eine Code-Implementierung zurückgegeben werden können. Dieselbe Obergrenze gilt für die Größe des Ergebnisses, das von einer Code-Implementierung zurückgegeben wird. <span id="Compositions"></span> == Kompositionen == Im diesem Abschnitt geben wir ein konkretes Beispiel, wie man eine Implementierung in Form einer Komposition erstellt. Angenommen, wir möchten eine Implementierung für eine Funktion erstellen, die zwei Eingabezeichenketten durch Einfügen eines Leerzeichens dazwischen kombiniert und das Ergebnis zurückgibt. Nehmen wir an, die ZID dieser Funktion ist <code>Z30000</code>. Normalerweise ist es sinnvoll, zunächst darüber nachzudenken, wie man vorhandene Funktionen kombinieren kann, um die gewünschte Ausgabe zu erzielen. Manchmal mag dies trivial sein und du kannst einfach mit dem Zusammenstellen und Funktionen fortfahren, aber in vielen Fällen lohnt es sich, die gewünschte Komposition zu notieren. Beispielsweise könnten wir für die angegebene Funktion die vorhandene Funktion {{Z|Z10000}} verwenden. Diese Funktion nimmt zwei Zeichenketten und erstellt daraus eine Zeichenkette. Aber wir müssen dazwischen ein Leerzeichen einfügen. Wir verbinden also zunächst ein Leerzeichen mit dem Ende der ersten Zeichenkette und verbinden dann die zweite Zeichenfolge mit dem Ergebnis dieser ersten Verbindung. Unsere Komposition könnte also so notiert werden: <syntaxhighlight lang="prolog"> join_strings( join_strings( Z30000K1, " " ), Z30000K2 ) </syntaxhighlight> Es gibt mehrere Möglichkeiten, eine Komposition zu schreiben: Beachte, dass dasselbe auch auf folgende Weise erreicht werden kann: <syntaxhighlight lang="prolog"> join_strings( Z30000K1, join_strings( " ", Z30000K2 ) ) </syntaxhighlight> Eine alternative Implementierung könnte auch die vorhandene Funktion {{Z|Z15175}} verwenden, sodass deine Komposition wie folgt aussehen könnte: <syntaxhighlight lang="prolog"> join_with_separator( Z30000K1, Z30000K2, " " ) </syntaxhighlight> Wie du siehst, gibt es mehrere Möglichkeiten, dies zu erreichen. Nimm dir also Zeit und erkunde die vorhandenen Funktionen, die im {{ll|Wikifunctions:Catalogue}} verfügbar sind. Versuchen wir, das zweite Beispiel zu erstellen, <code>join_strings(Z30000K1, join_strings(" ", Z30000K2))</code>. Um dies zu erstellen: # Um eine Implementierung hinzuzufügen, klicke auf der Funktionsseite in der Tabelle "Implementierungen" auf die Schaltfläche "+". # Stelle sicher, dass die Option "Komposition" unter "Implementierung" ausgewählt ist. # Klicke auf das Symbol "›" oder auf den Link "Funktion auswählen", um die Funktionsdetails anzuzeigen. # Suche unter "Funktion" nach dem Namen der äußersten Funktion, die du verwenden möchtest, in diesem Beispiel "verbinde Zeichenketten". Wähle anschließend die gewünschte Funktion aus der Dropdown-Liste aus. # Du siehst zwei neue Felder, eines für jedes der Argumente, die für die ausgewählte Funktion benötigt werden. # Als erstes Argument möchten wir den ersten Eingabewert für unsere Funktion auswählen: ## Klicke neben "erste Zeichenkette" auf die Schaltfläche "…" und wähle "Argumentreferenz" aus. ## Unter "Schlüssel-ID" kannst du nun die erste Zeichenkette deiner Funktion aus dem Dropdown-Menü auswählen, das alle verfügbaren Eingaben enthält. # Für das zweite Argument möchten wir das Ergebnis eines weiteren Aufrufs von "verbinde Zeichenketten" verwenden: ## Klicke neben "zweite Zeichenkette" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus. ## Suche unter "Funktion" nach der Funktion, die du aufrufen möchtest und wähle sie aus, nämlich "verbinde Zeichenketten". ## Konfiguriere die "erste Zeichenkette" für diesen inneren Funktionsaufruf, indem du einfach ein Leerzeichen in das Textfeld eingibst, und konfiguriere die "zweite Zeichenkette" wie in Schritt 6: Ändere sie mit der Schaltfläche "…" in "Argumentreferenz" und wähle dann das zweite Argument in der Dropdown-Liste aus. Deine Komposition ist nun fertig! Du kannst die Details mithilfe der Pfeiltasten ein- und ausblenden, um dir einen Überblick zu verschaffen. Falls du bereits Tests wie im Abschnitt [[#Practice Test-Driven Development|TDD]] oben empfohlen implementiert hast, klicke im Testbereich auf den kreisförmigen Pfeil und prüfe, ob deine Implementierung die Tests besteht. Sobald deine Komposition die Tests bestanden hat, kannst du sie veröffentlichen. [[File:Composition implementation expanded.png|frame|center|alt=Eine Wikifunctions-Kompositionsimplementierung in ihrer erweiterten Ansicht|Eine Wikifunctions-Kompositionsimplementierung in ihrer erweiterten Ansicht]] [[File:Composition implementation collapsed.png|frame|center|alt=Eine Wikifunctions-Kompositionsimplementierung in ihrer reduzierten Ansicht|Eine Wikifunctions-Kompositionsimplementierung in ihrer reduzierten Ansicht]] <span id="Wikifunctions_error_handling"></span> == Fehlerbehandlung auf Wikifunctions == Als Ersteller einer Wikifunctions-Funktion möchtest du möglicherweise den Benutzer warnen, der deine Funktion aufruft, wenn im Code ein Fehler auftritt oder seine Eingaben bestimmte Kriterien nicht erfüllen. Wenn deine Funktion beispielsweise eine Zeichenkette mit einem Namen erwartet, solltest du prüfen, ob der Name nicht leer ist, und gegebenenfalls eine verständliche Fehlermeldung anzeigen. Hierfür kannst du <code>Wikifunctions.Error()</code> in deinen Code-Implementierungen oder die Funktion {{Z|Z851}} in deinen Kompositionen verwenden. In diesem Abschnitt erfährst du: * Wie man Fehler sowohl aus Code- als auch aus Kompositions-Implementierungen auslöst, * wie man Tests für Fehlerfälle schreibt, und * wie man Fehler abfängt und behandelt, die von Funktionen ausgelöst werden, die man in seinen Kompositionen verwendet. <span id="Throwing_errors_from_code_implementations"></span> === Fehler aus Code-Implementierungen auslösen === Sowohl beim Schreiben von JavaScript- als auch von Python-Code kannst du <code>Wikifunctions.Error()</code> nutzen, um die Ausführung mit einem gewünschten Fehler zu beenden. <code>Wikifunctions.Error()</code> hat zwei Parameter: # Fehlertyp: Eine Zeichenkette, die die ZID des Fehlertyps enthält, den du zurückgeben möchtest. # Fehlerargumente: Eine Liste von Zeichenkettenargumenten zur Erstellung des Fehlers. Gehen wir sie der Reihe nach durch: <span id="Error_type"></span> ==== Fehlertyp ==== Ein Fehlertyp ist ein Objekt, das eine Art von Fehler beschreibt, der im System auftreten kann. Es gibt eine Reihe vordefinierter Fehlertypen, du kannst aber auch eigene Fehlertypen erstellen, die besser zu deinem Anwendungsfall passen. Bei der Verwendung von Fehlern empfiehlt es sich, die verfügbaren Fehlertypen zu durchsuchen, die sich in [[Special:ListObjectsByType/Z50|dieser Liste]] finden. Falls keine passenden Fehler für deinen Fall vorhanden sind, erstelle einen neuen Fehler, indem du zur Erstellungsseite gehst und im Typauswahlfeld "Fehlertyp" auswählst. Lege anschließend die erforderlichen Felder fest: [[File:Error type.png|thumb|alt=Erstellung von Fehlertypen in Wikifunctions|Um einen neuen Fehlertyp (Z50) zu erstellen, bearbeite die Bezeichnung und füge die erforderlichen Schlüssel hinzu.]] * '''Bezeichnung''' – Dies ist der Haupttitel des Fehlers, der eine kurze, aber aussagekräftige Meldung enthalten sollte. Lege die Fehlerbezeichnung im rechten Feld mit dem Titel "Info" fest. * '''Schlüssel''' – Schlüssel enthalten zusätzliche Informationen zur Fehlerursache. Wenn beispielsweise eine Eingabe das falsche Format aufwies, möchtest du den Benutzer möglicherweise über den eingegebenen Inhalt informieren, wenn der Fehler auftritt. Um sie in deinen Implementierungen zu verwenden, müssen Schlüssel vom Zeichenketten sein. Um einen Schlüssel zu erstellen, klicke auf das Symbol "[+]" unterhalb von "Schlüssel", wähle unter "Werttyp" die Option "Zeichenkette" aus und füge eine aussagekräftige Bezeichnung hinzu, beispielsweise "tatsächlich Eingabe". Sobald du alle erforderlichen Schlüssel erstellt hast, kannst du deinen Fehlertyp veröffentlichen und die ID des neu erstellten Objekts speichern. * '''Fehlermeldung''' – Fehlertypen können ein mehrsprachiges Array von Fehlermeldungen enthalten, die mit HTML-Parametern versehen sind. Die Parameter werden als $1, $2 etc. angegeben, wobei die Ziffer dem Schlüssel des Fehlertyps entspricht. Beim Erstellen eines Fehlertyps mit dem Zeichenketten-Schlüssel "aktuelle Eingabe", kann die Fehlermeldung beispielsweise den Platzhalter "$1" verwenden, der zum Zeitpunkt der Fehlerausgabe durch den Wert des Schlüssels "aktuelle Eingabe" ersetzt wird. Um HTML-Meldungen hinzuzufügen, klicke unter "HTML-Fragmente" auf das Symbol "[+]", wähle eine Sprache aus und gib die HTML-Zeichenkette ein. <span id="Error_arguments"></span> ==== Fehlerargumente ==== Fehlerargumente entsprechen den Schlüsseln des Fehlertyps und sollten zusätzliche Informationen zum Verständnis des Fehlers liefern. Fehlerargumente sollten immer Zeichenketten sein. <span id="Using_Wikifunctions.Error()"></span> ==== Verwendung von Wikifunctions.Error() ==== Angenommen, du möchtest einen Fehler auslösen, wenn entweder deine erste oder deine zweite Eingabe leer ist. Du hast den Fehlertyp bereits erstellt und ihm wurde die ZID <code>Z30005</code> zugewiesen. Dein Fehlertyp hat zwei Zeichenketten-Schlüssel: * Eingabeschlüssel: Enthält den Schlüssel der fehlerhaften Eingabe * Eingabewert: Enthält den aktuellen Wert der fehlerhaften Eingabe Um einen Fehler in deiner JavaScript-Implementierung auszulösen, solltest du etwa Folgendes tun: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1, Z30000K2 ) { if ( trim( Z30000K1 ) === '' ) { // Wenn die erste Eingabe leer ist, löse Fehler Z30005 aus // mit zwei Zeichenketten-Argumenten: [ erster Eingabe-Schlüssel, erster Eingabe-Wert ] Wikifunctions.Error( 'Z30005', [ "Z30000K1", Z30000K1 ] ) } if ( trim( Z30000K2 ) === '' ) { // Wenn die zweite Eingabe leer ist, löse Fehler Z30005 aus // mit zwei Zeichenketten-Argumenten: [ zweiter Eingabe-Schlüssel, zweiter Eingabe-Wert ] Wikifunctions.Error( 'Z30005', [ "Z30000K2", Z30000K2 ] ) } return Z30000K1 + " " + Z30000K2; } </syntaxhighlight> Um einen Fehler in deiner Python-Implementierung auszulösen, solltest du etwa Folgendes tun: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): if Z30000K1.strip() == "": # Wenn die erste Eingabe leer ist, löse Fehler Z30005 aus # mit zwei Zeichenketten-Argumenten: [ erster Eingabe-Schlüssel, erster Eingabe-Wert ] Wikifunctions.Error("Z30005", ["Z30000K1", Z30000K1]) if Z30000K2.strip() == "": # Wenn die zweite Eingabe leer ist, löse Fehler Z30005 aus # mit zwei Zeichenketten-Argumenten: [ erster Eingabe-Schlüssel, erster Eingabe-Wert ] Wikifunctions.Error("Z30005", ["Z30000K2", Z30000K2]) return Z30000K1 + " " + Z30000K2 </syntaxhighlight> Denke daran, dass der Aufruf von <code>Wikifunctions.Error()</code> die Ausführung beendet! <span id="Throwing_errors_from_compositions"></span> === Fehler aus Kompositionen auslösen === Wenn du eine Kompositionsimplementierung erstellst, kannst du einen Fehler auslösen, indem du die Spezialfunktion {{Z|Z851}} aufrufst. <span id="Throw_Error_function_(Z851)"></span> ==== Funktion Fehler auslösen (Z851) ==== Die Funktion {{Z|Z851}} ähnelt der Methode <code>Wikifunctions.Error()</code> und benötigt zwei Argumente: * '''Fehlertyp''' – Ein Verweis auf den Fehlertyp, den du auslösen möchtest * '''Fehlerparameter''' – Eine Liste mit den Argumenten zur Erstellung deines Fehlers, die ebenfalls Zeichenketten sein sollten. <span id="Using_Throw_Error"></span> ==== Verwendung von Fehler auslösen ==== Angenommen, du möchtest deine Komposition so ändern, dass sie zuerst prüft, ob die Argumente nicht leer sind, und einen Fehler ausgibt, wenn sie ein leeres Argument findet. Wenn dann keines der Argumente leer ist, wird die ursprüngliche Komposition ausgeführt, die wie folgt aussieht: <syntaxhighlight lang="prolog"> join_with_separator( Z30000K1, Z30000K2, " " ) </syntaxhighlight> Dazu musst du bedingte Pfade erstellen, für die du die Funktion {{Z|Z802}} verwenden kannst. Stell es dir folgendermaßen vor: * Wenn das erste Argument leer ist, soll ein Fehler für das erste Argument ausgelöst werden * Andernfalls wird mit der Überprüfung des zweiten Arguments fortgefahren * Wenn das zweite Argument leer ist, soll ein Fehler für das zweite Argument ausgelöst werden * Andernfalls wird der Erfolgspfad verfolgt und die verbundenen Zeichenketten mit dem Leerzeichen als Trennzeichen zurückgegeben Oder in funktionalem Pseudocode: <syntaxhighlight lang="prolog"> if ( is_empty_string( Z30000K1 ), throw_error( Z30005, [ "Z30000K1", Z30000K1 ] ), if( is_empty_string( Z30000K2 ), throw_error( Z30005, [ "Z30000K2", Z30000K2 ] ), join_with_separator( Z30000K1, Z30000K2, " " ) ) ) </syntaxhighlight> Lass uns das Schritt für Schritt erstellen: # Um eine Implementierung hinzuzufügen, klicke auf der Funktionsseite in der Tabelle "Implementierungen" auf die Schaltfläche "+". # Stelle sicher, dass die Option "Komposition" unter "Implementierung" ausgewählt ist. # Klicke auf das Symbol "›" oder auf den Link "Funktion auswählen", um die Funktionsdetails anzuzeigen. # Suche unter "Funktion" nach der äußersten Funktion, die du verwenden möchtest, in diesem Fall "wenn", und wähle sie aus. # Überprüfe die Gültigkeit des ersten Arguments: ## Klicke neben "Bedingung" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "ist leere Zeichenkette" und wähle sie aus ## Klicke neben "Eingabe" auf die Schaltfläche "…" und wähle "Argumentreferenz" aus ## Wähle unter "Schlüssel-ID" die erste Eingabe aus (z. B. "erste Zeichenkette") ## Du kannst den Funktionsaufruf der "Bedingung" nun bei Bedarf ausblenden, indem du auf den Pfeil nach unten neben "Bedingung" klickst. Es sollte dann etwa Folgendes angezeigt werden: "f(x) ist leere Zeichenkette ( → erste Zeichenkette )" # Fehler auslösen, wenn die Bedingung wahr ist: ## Klicke neben "dann" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "Fehler auslösen" und wähle sie aus ## Suche unter "Fehlertyp" nach deinem Fehlertyp (du kannst die Fehler-ID direkt eingeben, wenn du sie kennst, z. B. Z30005) und wähle ihn aus ## Füge unter "Fehlerparameter" zwei Elemente hinzu, indem du auf die Schaltfläche "+" klickst ## Lege für "Objekt 1" (fehlerhafter Argumentschlüssel) den Typ auf "Zeichenkette" fest und trage die Argumentkennung ein (z. B. "erste Eingabe" oder "Z30000K1") ## Klicke für "Objekt 2" (fehlerhafter Argumentwert) auf die "…" neben "Objekt 2" und wähle "Argumentreferenz" aus ## Wähle unter "Schlüssel-ID" die erste Eingabe aus (z. B. "erste Zeichenkette") ## Du kannst den Funktionsaufruf "dann" nun bei Bedarf ausblenden, indem du auf den Pfeil nach unten neben "dann" klickst. Es sollte dann etwa Folgendes angezeigt werden: "f(x) Fehler auslösen ( ungültiges Format, typisierte Liste ( Objekt, "erste Eingabe", → erste Zeichenkette ) )" # Prüfe das zweite Argument, wenn das erste korrekt war: ## Klicke neben "sonst" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "wenn" und wähle sie aus ## Richte eine "Bedingung" ein, um die Gültigkeit des zweiten Arguments zu überprüfen, indem du das gleiche Verfahren wie in Schritt 5 beschrieben anwendest. ## Richte "dann" so ein, dass beim zweiten Argument ein Fehler ausgelöst wird, indem du das gleiche Verfahren wie in Schritt 6 beschrieben anwendest. # Richte schließlich den Erfolgspfad ein: ## Klicke neben dem verschachtelten "sonst" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der gewünschten Funktion, in diesem Fall "vereinige zwei Zeichenketten mit Trennzeichen", und wähle sie aus ## Klicke neben "erste Zeichenkette" auf die Schaltfläche "…" und setze sie auf "Argumentreferenz", wähle anschließend "erste Zeichenkette" aus ## Klicke neben "zweite Zeichenkette" auf die Schaltfläche "…" und setze sie auf "Argumentreferenz", wähle anschließend "zweite Zeichenkette" aus ## Füge unter "Trennzeichen" ein Leerzeichen in das Textfeld ein Der resultierende Funktionsaufruf sollte folgendermaßen aussehen: [[File:Throw error expanded.png|frame|center|alt=Wikifunctions-Komposition mit der Funktion Fehler auslösen|Wikifunctions-Komposition mit der Funktion Fehler auslösen]] [[File:Throw error collapsed.png|frame|center|alt=Wikifunctions-Komposition mit der Funktion Fehler auslösen in ihrer reduzierten Ansicht|Wikifunctions-Komposition mit der Funktion Fehler auslösen in ihrer reduzierten Ansicht]] <span id="Handling_errors_in_compositions"></span> === Fehlerbehandlung in Kompositionen === Es ist zwar nützlich, Funktionen das Auslösen erwarteter Fehler zu ermöglichen, aber es ist entscheidend, Fehler in den eigenen Kompositionen behandeln zu können, um diese Funktionen sicher verwenden zu können. Angenommen, du möchtest eine neue Funktion "vollständiger Name einer Person" erstellen – wir bezeichnen sie mit der ZID <code>Z30010</code>. Diese Funktion soll den vollständigen Namen einer Person anhand ihres Vor- und Nachnamens zurückgeben. Ist jedoch eines der beiden Felder leer, soll sie stattdessen den Text "Unbekannt" zurückgeben. Du könntest eine Komposition erstellen, indem du unsere Beispielfunktion "verbinde zwei Zeichenketten mit Leerzeichen" oder <code>Z30000</code> verwendest, um den Namen zu generieren. Wenn eine der Eingaben leer ist, weißt du, dass <code>Z30000</code> einen Fehler vom Typ <code>Z30005</code> auslöst. Mithilfe der Funktion {{Z|Z850}} als Wrapper kannst du die Verbindungsoperation ausführen und einen möglichen Fehler abfangen, indem du einfach "Unbekannt" zurückgibst, wenn er auftritt. <span id="Try-Catch_function_(Z850)"></span> ==== Try-Catch-Funktion (Z850) ==== Die Funktion {{Z|Z850}} ist eine integrierte Funktion mit der ZID <code>Z850</code> und benötigt drei Argumente: * '''Funktionsaufruf''' – Der erste Funktionsaufruf, der ausgeführt werden soll. Wenn kein Fehler auftritt, ist die Antwort das Ergebnis dieses Funktionsaufrufs. * '''Fehlertyp''' – Ein Fehlertyp, der abgefangen werden soll, falls er während der Ausführung des ersten Funktionsaufrufs auftritt. * '''Fehlerhandler''' – Ein Funktionsaufruf, der ausgeführt wird, falls der oben genannte Fehler während der Ausführung des ursprünglichen Funktionsaufrufs auftritt. In diesem Fall wird das Ergebnis der Fehlerbehandlung zurückgegeben. <span id="Using_Try-Catch"></span> ==== Verwendung der Try-Catch-Funktion ==== Sobald wir alle Funktionen für unsere Komposition haben, können wir sie folgendermaßen gestalten: <syntaxhighlight lang="prolog"> try_catch( join_with_space( Z30010K1, Z30010K2 ), Z30005, echo( "Unknown" ) ) </syntaxhighlight> Das bedeutet: * Die Funktion "verbinde zwei Zeichenketten mit Leerzeichen" wird mit den beiden Eingaben ausprobiert und wenn alles erfolgreich verläuft, wird das Ergebnis dieser Funktion zurückgegeben * Wenn eine der Eingaben leer ist, löst "verbinde zwei Zeichenketten mit Leerzeichen" einen Fehler vom Typ <code>Z30005</code> aus * Unsere {{Z|Z850}} erkennt dann diesen Fehler und führt die Funktion {{Z|Z801}} aus, die "Unbekannt" zurückgibt Lass uns das Schritt für Schritt erstellen: # Um eine Implementierung hinzuzufügen, klicke auf der Funktionsseite in der Tabelle "Implementierungen" auf die Schaltfläche "+". # Stelle sicher, dass die Option "Komposition" unter "Implementierung" ausgewählt ist. # Klicke auf das Symbol "›" oder auf den Link "Funktion auswählen", um die Funktionsdetails anzuzeigen. # Suche unter "Funktion" nach der äußersten Funktion, die du verwenden möchtest, in diesem Fall "Try-Catch-Funktion", und wähle sie aus. # Richte den Hauptfunktionsaufruf ein: ## Klicke unterhalb des Feldes, in dem die "Try-Catch-Funktion" ausgewählt ist, neben dem Schlüssel "Funktionsaufruf" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "verbinde zwei Zeichenketten mit Leerzeichen" und wähle sie aus ## Klicke neben "erste Zeichenkette" auf die Schaltfläche "…" und wähle "Argumentreferenz" aus, wähle anschließend das Argument "erster Name" aus der Dropdown-Liste aus. ## Klicke neben "zweite Zeichenkette" auf die Schaltfläche "…" und wähle "Argumentreferenz" aus, wähle anschließend das Argument "zweiter Name" aus der Dropdown-Liste aus. # Wähle den abzufangenden Fehler aus: ## Suche unter "Fehlertyp" nach "ungültige Zeichenkette" und wähle es aus – du kannst direkt nach der ZID <code>Z30005</code> suchen # Richte den Funktionsaufruf für den Fehlerhandler ein: ## Klicke neben "Fehlerhandler" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "Echo" und wähle sie aus ## Suche unter "Eingabe" und "Typ" den Typ "Zeichenkette" und wähle ihn aus ## Gib nun unter "Eingabe" im Textfeld "Unbekannt" ein Die resultierende Funktion sollte folgendermaßen aussehen: [[File:Try catch expanded.png|frame|center|alt=Wikifunctions-Komposition mit der Try-Catch-Funktion in ihrer erweiterten Ansicht|Wikifunctions-Komposition mit der Try-Catch-Funktion in ihrer erweiterten Ansicht]] [[File:Try catch collapsed.png|frame|center|alt=Wikifunctions-Komposition mit der Try-Catch-Funktion in ihrer reduzierten Ansicht|Wikifunctions-Komposition mit der Try-Catch-Funktion in ihrer reduzierten Ansicht]] <span id="Testing_your_failure_use_cases"></span> === Testen deiner Fehlerfälle === Wie bereits im Abschnitt über die [[#Practice Test-Driven Development|Anwendung von TDD]] erläutert, ist es wichtig, nicht nur die häufigsten Ausführungspfade, sondern auch mögliche Randfälle zu testen. Ebenso wichtig ist es, das Fehlerverhalten zu prüfen. In diesem Abschnitt stellen wir dir die notwendigen Werkzeuge vor, um zu testen, ob deine Funktion bei bestimmten Eingaben fehlschlägt und ob die Fehlermeldung den Erwartungen entspricht. Dazu benötigst du zwei weitere Systemfunktionen: <span id="Is_error_type_(Z852)"></span> ==== ist Fehlertyp (Z852) ==== Die Funktion {{Z|Z852}} ist eine integrierte Funktion mit der ZID <code>Z852</code> und benötigt zwei Argumente: * '''Fehler''' – Ein {{Z|Z5}}-Objekt, das bei einem fehlgeschlagenen Aufruf ausgelöst werden kann. Eine Fehlerinstanz hat einen Typ und einen Wert. * '''Fehlertyp''' – Ein Verweis auf einen {{Z|Z50}}, der mit dem als erstes Argument übergebenen Fehlertyp verglichen wird. Ist dies der Fall, gibt die Funktion wahr zurück. <span id="Get_error_thrown_by_function_call_(Z853)"></span> ==== Fehler erhalten, ausgelöst durch Funktionsaufruf (Z853) ==== Die Funktion {{Z|Z853}} ist eine integrierte Funktion mit der ZID <code>Z853</code> und benötigt ein Argument: * '''Funktionsaufruf''' – Ein Funktionsaufruf, der entweder einen erfolgreichen Wert beliebigen Typs zurückgibt oder einen Fehler auslöst. Diese Funktion gibt ein {{Z|Z882}} zurück, wobei an erster Stelle ein {{Z|Z40}} und an zweiter Stelle ein {{Z|Z1}} steht: * Wenn der Funktionsaufruf erfolgreich ist und somit keinen Fehler auslöst, enthält das zurückgegebene Paar an erster Stelle falsch und an zweiter Stelle leer. * Wenn der Funktionsaufruf einen Fehler auslöst, enthält das zurückgegebene Paar an erster Stelle wahr und an zweiter Stelle den abgefangenen Fehler. Um diese Funktion in deinen Kompositionen zu verwenden, musst du möglicherweise die zusätzlichen Funktionen verwenden: * {{Z|Z821}} und * {{Z|Z822}} <span id="Testing_errors"></span> ==== Fehler testen ==== Angenommen, unsere Zielfunktion "verbinde zwei Zeichenketten mit Leerzeichen" oder <code>Z30000</code> löst einen Fehler vom Typ <code>Z30005</code> aus, und wir möchten dieses Verhalten testen. Dazu müssen wir Folgendes tun: * Einen fehlgeschlagenen Funktionsaufruf auslösen * Den Fehler mit der Funktion {{Z|Z853}} erhalten * Mit {{Z|Z852}} prüfen, ob der Fehler den richtigen Typ hat Tests haben zwei Felder: * '''Aufruf''' – Ein Funktionsaufruf, der mit den zu testenden Eingaben eine Ausgabe erzeugt. Dieser Aufruf gibt einen Wert zurück. * '''Ergebnisprüfung''' – Ein Funktionsaufruf, der überprüft, ob der vom vorherigen Aufruf zurückgegebene Wert dem erwarteten Wert entspricht. Das erste Argument dieses Funktionsaufrufs wird automatisch mit dem Rückgabewert des ersten Aufrufs belegt. Für eine Schritt-für-Schritt-Anleitung zum Erstellen von Tests siehe {{ll|Wikifunctions:Introduction#Create_tests}}. In unserem Beispiel können wir es so strukturieren — aber das ist nicht die einzige Möglichkeit! Der Aufruf, der ein {{Z|Z5}}-Objekt zurückgibt: <syntaxhighlight lang="prolog"> error = get_second_element_of_typed_list( get_error_thrown_by( join_strings_by_whitespace( "", "not empty" ) ) ) </syntaxhighlight> Und die Ergebnisprüfung, die das {{Z|Z5}}-Objekt als erstes Argument verwendet: <syntaxhighlight lang="prolog"> is_error_type( error, Z30005 ) </syntaxhighlight> Lass uns das Schritt für Schritt tun: # Um einen Test hinzuzufügen, klicke auf der Funktionsseite in der Tabelle "Tests" auf die Schaltfläche "+". Die Felder "Aufruf" und "Ergebnisprüfung" enthalten bereits vordefinierte Funktionen. Um die Fehler zu testen, müssen wir diese jedoch ändern. # Als Erstes richten wir den Aufruf ein: ## Klicke unter "Aufruf" auf die Schaltfläche "›", um den Funktionsaufruf zu erweitern. ## Bearbeite das Feld unter "Funktion" und suche die Funktion "erhalte zweites Element eines typisierten Paars" und wähle sie aus ## Klicke anschließend neben "typisiertes Paar" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "Fehler erhalten, ausgelöst durch Funktionsaufruf" und wähle sie aus ## Klicke neben "Funktionsaufruf" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "verbinde zwei Zeichenketten mit Leerzeichen" (oder nach ZID <code>Z30000</code>) und wähle sie aus ## Lege nun die Eingaben so fest, dass ein Fehler auftritt: Mindestens eine von ihnen muss leer sein. ## Du kannst jetzt deinen "Aufruf" durch erneutes Klicken auf den Pfeil nach unten wieder ausblenden, wenn du möchtest! # Als Nächstes richten wir die Ergebnisprüfung ein: ## Klicke unter "Ergebnisprüfung" auf die Schaltfläche "›", um den Funktionsaufruf zu erweitern. ## Bearbeite das Feld unter "Funktion" und suche die Funktion "ist Fehlertyp" und wähle sie aus ## Du wirst nun nur noch aufgefordert, das zweite Argument zu konfigurieren. Suche unter "Fehlertyp" nach deinem Fehlertyp <code>Z30005</code> und wähle ihn aus. # Und du bist fertig! Du kannst jetzt auf den kreisförmigen Pfeil im Feld "Implementierungen" klicken und solltest grüne Häkchen sehen. Wenn alles geklappt hat, kannst du deinen Test jetzt speichern. Er sollte folgendermaßen aussehen: [[File:Get error expanded.png|frame|center|alt=Testen eines Fehlers mit den Funktionen Fehler erhalten und ist Fehlertyp in ihrer erweiterten Ansicht|Testen eines Fehlers mit den Funktionen Fehler erhalten und ist Fehlertyp in ihrer erweiterten Ansicht]] [[File:Get error collapsed.png|frame|center|alt=Testen eines Fehlers mit den Funktionen Fehler erhalten und ist Fehlertyp in ihrer reduzierten Ansicht|Testen eines Fehlers mit den Funktionen Fehler erhalten und ist Fehlertyp in ihrer reduzierten Ansicht]] <span id="Creating_actionable_error_messages"></span> === Erstellung handlungsorientierter Fehlermeldungen === Wie oben beschrieben, verfügen Fehlertypen über einen optionalen Schlüssel <code>Z50K3</code>, der eine mehrsprachige Liste von HTML-Zeichenketten enthält. Bei der Darstellung von Informationen zu einem Fehler können die im Fehlertyp hinterlegten Meldungen dazu beitragen, eine klare, präzise, ​​informative, übersetzbare und handlungsorientierte Fehlermeldung zu erstellen. <div lang="en" dir="ltr" class="mw-content-ltr"> For that purpose, error messages can contain parameters like <code>$1</code>, <code>$2</code>, etc., where the digit corresponds to the error type argument and its value in the error instance. These error messages are rendered in Wikifunctions inside the "Details" dialog window after executing a function call. Additionally, these error messages are surfaced in other client interfaces, like Abstract Wikipedia, to provide better guidance to Abstract Content editors. </div> [[File:Wikifunctions actionable error message example in the Details dialog.png|thumb|<span lang="en" dir="ltr" class="mw-content-ltr">The error message is rendered using the HTML message of the error type and the error argument values.</span>]] [[File:Wikifunctions actionable error message example in Abstract Wikipedia.png|thumb|<span lang="en" dir="ltr" class="mw-content-ltr">When available, the HTML error message is rendered in the Abstract Wikipedia preview section.</span>]] <div lang="en" dir="ltr" class="mw-content-ltr"> Let's use a real example to understand the benefits of HTML error messages: </div> <div lang="en" dir="ltr" class="mw-content-ltr"> The function {{Z|Z37847}} returns the first Lexeme reference given a Wikidata Item reference and a language. When there is no Lexeme for this Item-Language combination, it throws an error of type {{Z|Z28248}}, which has three keys: </div> * <span lang="en" dir="ltr" class="mw-content-ltr">'''Z28248K1''' is the input Wikidata item QID</span> * <span lang="en" dir="ltr" class="mw-content-ltr">'''Z28248K2''' is the connecting property, in this case <code>P5137/item for this sense</code></span> * <span lang="en" dir="ltr" class="mw-content-ltr">'''Z28248K3''' is the language code</span> <div lang="en" dir="ltr" class="mw-content-ltr"> When calling this function for a Wikidata lexeme that doesn't exist, the call will throw an error instance like this: </div> <syntaxhighlight lang="json" highlight="10,12"> { "Z1K1": "Z5", "Z5K1": "Z28248", "Z5K2": { "Z1K1": { "Z1K1": "Z7", "Z7K1": "Z885", "Z885K1": "Z28248" }, "Z28248K1": "Q319", "Z28248K2": "P5137", "Z28248K3": "ast" } } </syntaxhighlight> <div lang="en" dir="ltr" class="mw-content-ltr"> While the error type label indicates: <code>No matching lexeme for item in language</code>, a better error message should indicate: </div> * <span lang="en" dir="ltr" class="mw-content-ltr">which is the failing item,</span> * <span lang="en" dir="ltr" class="mw-content-ltr">which is the language missing, and</span> * <span lang="en" dir="ltr" class="mw-content-ltr">what are the possible ways to fix it.</span> <div lang="en" dir="ltr" class="mw-content-ltr"> The error message <code>Z50K3</code> field can provide this functionality. Whenever an Error Type has an error message for the user language (or any of its fallbacks), the error message shown will be rendered by: </div> # <span lang="en" dir="ltr" class="mw-content-ltr">First, replacing the message parameters with the values of the keys. In our example, any <code>$1</code> will be replaced with the value of <code>Z28248K1</code> ("Q319"), <code>$2</code> with "P5137", and <code>$3</code> with "ast",</span> # <span lang="en" dir="ltr" class="mw-content-ltr">Last, sanitizing and rendering the HTML message.</span> <div lang="en" dir="ltr" class="mw-content-ltr"> So a HTML message like: </div> <syntaxhighlight lang="html"> There is no matching lexeme for the item $1 in "$3".<br> <a href="http://wikidata.org/wiki/$1">Edit in Wikidata</a> </syntaxhighlight> <div lang="en" dir="ltr" class="mw-content-ltr"> Will become: </div> : There is no matching lexeme for the item Q319 in "ast" : [[d:Q319|Edit in Wikidata]] <span id="Debugging_your_implementations"></span> == Debuggen deiner Implementierungen == Manchmal läuft etwas schief. Eine Funktion verhält sich möglicherweise anders als erwartet oder ein Wert erscheint merkwürdig. Implementierungen können mitunter sehr komplex sein, und da sie in einer Spielwiesen-Umgebung ausgeführt werden, kann die Fehlersuche extrem schwierig erscheinen. Um das Verständnis der Vorgänge innerhalb eines Funktionsaufrufs zu erleichtern, bietet Wikifunctions einige Debugging-Werkzeuge. Diese Werkzeuge verändern nicht das Ergebnis einer Funktion, sondern fügen den zurückgegebenen Metadaten zusätzliche Informationen hinzu, die du nach dem Ausführen der Funktion einsehen kannst. Du kannst <code>Wikifunctions.Debug()</code> in deinen Code-Implementierungen oder die Funktion {{Z|Z854}} in deinen Kompositionen verwenden. In diesem Abschnitt erfährst du: * Wie man Debug-Meldungen sowohl aus Code- als auch aus Kompositions-Implementierungen hinzufügt, * Wie man die Metadaten manuell oder über die Benutzeroberfläche untersucht, um diese Protokolle einzusehen. <span id="Debugging_your_code_implementations"></span> === Debuggen deiner Code-Implementierungen === Beim Schreiben von Code, sowohl in JavaScript als auch in Python3, kannst du <code>Wikifunctions.Debug()</code> verwenden, um eine Meldung zu deinem Debug-Protokoll hinzuzufügen und die Ausführung fortzusetzen. {{phab|T441028}} <code>Wikifunctions.Debug()</code> hat einen Parameter, der üblicherweise als Zeichenkette erwartet wird. Jedes andere als Parameter übergebene Objekt wird jedoch direkt in eine Zeichenkette umgewandelt. Um zu unseren Code-Implementierungen für unsere Beispielfunktion "verbinde zwei Zeichenketten mit Leerzeichen" Debug-Protokolle hinzuzufügen, können wir dies in JavaScript tun: <syntaxhighlight lang="JavaScript"> function Z30000( Z30000K1, Z30000K2 ) { if ( trim( Z30000K1 ) === '' ) { Wikifunctions.Debug( `first input is empty "${ Z30000K1 }"` ); Wikifunctions.Error( 'Z30005', [ "Z30000K1", Z30000K1 ] ) } if ( trim( Z30000K2 ) === '' ) { Wikifunctions.Debug( `second input is empty "${ Z30000K2 }"` ); Wikifunctions.Error( 'Z30005', [ "Z30000K2", Z30000K2 ] ) } Wikifunctions.Debug( "both inputs are fine" ); return Z30000K1 + " " + Z30000K2; } </syntaxhighlight> Und das Gleiche in deiner Python3-Implementierung: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): if Z30000K1.strip() == "": Wikifunctions.Debug( 'first input is empty "'+Z30000K1+'"' ) Wikifunctions.Error("Z30005", ["Z30000K1", Z30000K1]) if Z30000K2.strip() == "": Wikifunctions.Debug( 'second input is empty "'+Z30000K2+'"' ) Wikifunctions.Error("Z30005", ["Z30000K2", Z30000K2]) Wikifunctions.Debug( 'both inputs are fine' ) return Z30000K1 + " " + Z30000K2 </syntaxhighlight> Auf diese Weise fügen wir deinen Debug-Protokollen in jedem Fall eine Meldung hinzu: * Schlägt der Funktionsaufruf bei der Überprüfung der ersten oder zweiten Eingabe fehl, ist das Ergebnis der Ausführung ein Fehler, enthält aber einen informativen Protokolleintrag darüber, welcher Zweig den Fehler verursacht hat. * Wenn der Funktionsaufruf erfolgreich ist — weil beide Eingaben gültig sind — gibt der Funktionsaufruf die verbundene Zeichenkette zurück, aber die zurückgegebenen Metadaten enthalten auch ein Debug-Protokoll. <span id="Debugging_your_compositions"></span> === Debuggen deiner Kompositionen === Zur Unterstützung des Debuggens von Kompositionen stellt Wikifunctions die integrierte Funktion {{Z|Z854}} bereit. Mit dieser Funktion kannst du Debug-Meldungen an die Ausführung jedes Funktionsaufrufs anhängen, der die endgültige Ausgabe erzeugt. Die während der Auswertung gesammelten Debug-Protokolle werden als Teil der Ausführungsmetadaten unter dem Schlüssel <code>executorDebugLogs</code> zurückgegeben. <span id="Add_debug_log_to_function_call_(Z854)"></span> ==== Debug-Protokoll zu Funktionsaufruf hinzufügen (Z854) ==== Die Funktion {{Z|Z854}} ist eine integrierte Funktion mit der ZID <code>Z854</code> und benötigt zwei Argumente: * '''Funktionsaufruf''' – Jede Komposition, die du ausführen möchtest. * '''Debug-Protokoll''' – Eine Zeichenketten-Meldung, die protokolliert wird, wenn der angegebene Funktionsaufruf ausgewertet wird. Wenn der umschlossene Funktionsaufruf ausgeführt wird, wird die bereitgestellte Meldung zu den Ausführungsprotokollen hinzugefügt. Wird dieser Funktionsaufruf nicht ausgeführt oder ist seine Ausführung nicht Teil der endgültigen Ausgabe, erscheint sein Debug-Protokoll nicht in den Metadaten des Endergebnisses. Diese integrierte Funktion ist besonders nützlich, wenn du beobachten möchtest: * Welcher Zweig einer Bedingung ausgeführt wurde, oder * Die Reihenfolge der Auswertung in einer Komposition. <span id="Using_Add_debug_log_to_function_call"></span> ==== Verwendung von Debug-Protokoll zu Funktionsaufruf hinzufügen ==== Angenommen, du möchtest zu unserer Beispielfunktion "verbinde zwei Zeichenketten mit Leerzeichen" oder <code>Z30000</code> Debug-Protokolle hinzufügen, sodass für die verschiedenen möglichen Ergebnisse unterschiedliche Meldungen angezeigt werden. Du könntest unsere integrierte Debugging-Funktion wie folgt verwenden: <syntaxhighlight lang="prolog"> if ( is_empty_string( Z30000K1 ), add_debug_log( throw_error( Z30005, ... ), 'failed on first input' ) if( is_empty_string( Z30000K2 ), add_debug_log( throw_error( Z30005, ... ), 'failed on second input' ), add_debug_log( join_with_separator( Z30000K1, Z30000K2, " " ), 'both inputs are ok!' ) ) ) </syntaxhighlight> Dies bewirkt Folgendes: * Wird die Funktion mit einer leeren ersten Eingabe aufgerufen, gibt sie eine Fehlermeldung zurück und die Metadaten enthalten einen Eintrag <code>executorDebugLogs</code> mit dem Protokoll-Eintrag "Fehler bei erster Eingabe". * Wird der Aufruf mit einer leeren zweiten Eingabe aufgerufen, schlägt der Aufruf ebenfalls fehl, die protokollierte Meldung lautet jedoch "Fehler bei zweiter Eingabe". * Bei Aufruf mit gültigen Eingaben gibt die Funktion eine erfolgreiche Antwort zurück und zusätzlich enthalten die Metadaten im Schlüssel <code>executorDebugLogs</code> "Beide Eingaben sind in Ordnung". So würde diese Komposition aussehen: [[File:Add debug log expanded.png|frame|center|alt=Implementierung der Komposition mit Debug-Protokoll hinzufügen, um alle möglichen Ausführungspfade zu protokollieren|Implementierung der Komposition mit Debug-Protokoll hinzufügen, um alle möglichen Ausführungspfade zu protokollieren]] <span id="Accessing_execution_debug_logs"></span> === Zugriff auf Ausführungs-Debug-Protokolle === Unabhängig davon, ob deine Ausführungsprotokolle über <code>Wikifunctions.Debug()</code> oder die integrierte Funktion {{Z|Z854}} hinzugefügt werden, werden sie als Teil der Antwort-Metadaten zurückgegeben. Um die Protokolle zu sehen, klicke nach dem Ausführen deiner Funktion auf die Schaltfläche "Details", die unten im Abschnitt "Ergebnis" erscheint. Die Fehler- und Debug-Informationen werden oben im Dialogfeld "Details" angezeigt. Dies ist das Ergebnis, das du sehen würdest, wenn du die Komposition aus unserem vorherigen Beispiel mit gültigen und ungültigen Eingaben ausführst: {| class="wikitable" | [[File:Execution logs success.png|frameless|center|alt=Funktions-Metadatendialog für eine erfolgreiche Ausführung mit Debug-Protokollen]] | [[File:Execution logs failure.png|frameless|center|alt=Funktions-Metadatendialog für eine fehlgeschlagene Ausführung mit Debug-Protokollen]] |- | Funktions-Metadatendialog für eine erfolgreiche Ausführung: zeigt keine Fehler an, sondern das Protokoll der erfolgreichen Ausführung: ''"Beide Eingaben sind in Ordnung!"'' | Funktions-Metadatendialog für eine fehlgeschlagene Ausführung: zeigt die Fehlerinformationen und das zusätzliche Ausführungsprotokoll für den ersten Fehlerzweig an: ''"Fehler bei erster Eingabe"'' |} [[Category:How to create implementations| {{#translation:}}]] 2emwcpm1feyj4olzvbbs20m9uri6euq 333940 333938 2026-10-27T19:27:49Z Ameisenigel 44 Created page with "Zu diesem Zweck können Fehlermeldungen Parameter wie $1, $2 etc. enthalten, wobei die Ziffer dem Argument des Fehlertyps und dessen Wert in der Fehlerinstanz entspricht. Diese Fehlermeldungen werden in Wikifunctions nach der Ausführung eines Funktionsaufrufs im Dialogfenster "Details" angezeigt. Darüber hinaus werden diese Fehlermeldungen auch in anderen Client-Schnittstellen, wie der Abstrakten Wikipedia, ausgegeben, um den Autoren von Abstrakten Inhalten eine besser..." 333940 wikitext text/x-wiki <languages/> Diese Seite bietet eine detailliertere Anleitung dafür, wie man '''Implementierungen erstellt''' und geht über den Überblick auf {{ll|Wikifunctions:Introduction}} hinaus. <span id="Types_of_Implementations"></span> == Arten von Implementierungen == In Wikifunctions kann eine '''Implementierung''' zwei Hauptformen annehmen: '''Code''' oder '''Komposition'''. Eine Code-Implementierung drückt die Logik der Funktion direkt in einer der verfügbaren Programmiersprachen aus (derzeit Python3 oder JavaScript). Sie ist besonders nützlich, wenn sich das Verhalten der Funktion nicht ohne Weiteres aus bestehenden Wikifunktionen ableiten lässt oder wenn eine präzise Kontrolle über die Datenverarbeitung erforderlich ist. Eine Kompositions-Implementierung definiert die Funktion hingegen vollständig durch die Kombination bestehender Funktionen, ohne dass Code geschrieben werden muss. Kompositionen sind leichter verständlich, wiederverwendbar und lassen sich automatisch in andere Sprachen übersetzen. Sie setzen jedoch voraus, dass geeignete Bausteine ​​bereits vorhanden sind und sind oft weniger leistungsfähig. Prüfe daher zunächst, ob dein Ziel durch Komposition erreicht werden kann. Ist dies nicht möglich oder spielen Leistung oder feingranulare Logik eine Rolle, wähle stattdessen eine Code-Implementierung. Es gibt eine dritte Implementierungsart: '''integrierte Implementierungen'''. Diese werden vom Systemcode ausgeführt und können nicht bearbeitet werden. Höchstwahrscheinlich verfügen alle vordefinierten Funktionen über eine integrierte Implementierung. In solchen Fällen wird beim Öffnen der Implementierungsseite die Meldung ''"{{int|wikilambda-implementation-selector-none}}"'' angezeigt. <span id="Practice_Test-Driven_Development"></span> == Praxis der testgetriebenen Entwicklung == '''Testgetriebene Entwicklung''' oder '''TDD''' ist eine Methode zur Softwareentwicklung, bei der Tests geschrieben werden, bevor der eigentliche Code geschrieben wird. Tests dienen dazu, die Funktionsweise einer Funktion anhand von Beispielen und deren Funktionsweise zu verstehen. In Wikifunctions bietet das Schreiben von Tests als erste Tätigkeit erhebliche Vorteile. Wenn du an einer Implementierung arbeitest, kannst du deinen Code anhand der vorhandenen Tests ausführen, um sicherzustellen, dass er sich wie erwartet verhält. Dadurch lassen sich Fehler frühzeitig erkennen, noch bevor du deine Implementierung veröffentlichst. Tests sind außerdem ein effektives Mittel, um die benötigte Funktion zu beschreiben. Durch das Schreiben von Tests '''kommunizierst du klar das erwartete Verhalten''' und die Community kann bei der Implementierung helfen oder alternative Implementierungen erstellen. Stell dir vor, du möchtest eine Funktion implementieren, die zwei Zeichenketten mit einem Leerzeichen dazwischen verknüpft. Ein einfacher Test dafür könnte so aussehen: <syntaxhighlight lang="prolog"> join_with_space( "Hello", "world" ) => "Hello world" </syntaxhighlight> Sobald du das grundlegende Verhalten definiert hast, ist es wichtig, auch '''an Randfälle zu denken''' — Situationen, in denen die Eingaben so beschaffen sind, dass ein spezielles Verhalten erforderlich sein könnte. Was passiert beispielsweise, wenn deine erste Zeichenkette mit einem Leerzeichen endet oder deine zweite mit einem Leerzeichen beginnt? Soll die Funktion alle vorhandenen Leerzeichen beibehalten und ein weiteres hinzufügen oder ein sauber formatiertes Ergebnis mit nur einem Leerzeichen zwischen den Wörtern zurückgeben? Je nach deinen Anforderungen solltest du einen Test für einen solchen Fall erstellen. Ein Test für diesen Sonderfall könnte beispielsweise einer der folgenden sein — aber nicht beide!: <syntaxhighlight lang="prolog"> join_with_space( "Hello ", " world") => "Hello world" </syntaxhighlight> oder ... <syntaxhighlight lang="prolog"> join_with_space( "Hello ", " world") => "Hello world" </syntaxhighlight> Stell sicher, dass deine Tests alle möglichen Sonderfälle abdecken, und sobald du diese hast, stell sicher, dass sie alle mit der Funktion verbunden sind, indem du sie auswählst und auf "Verbinden" klickst. <span id="Code_implementations"></span> == Code-Implementierungen == [[File:Code implementation.png|thumb|alt=Wikifunctions-Code-Editor, der mit einer Funktionsvorlage initialisiert wurde|Beim Hinzufügen einer neuen Code-Implementierung wird die Funktionsvorlage mit den Funktions- und Argumentnamen initialisiert]] Beim Erstellen einer Implementierung mit Code richtet die Wikifunctions-Benutzeroberfläche einen Code-Editor ein, in dem die ausgewählte Sprache für Syntaxhervorhebung und -validierung aktiviert ist. Sobald die zu implementierende Funktion und die Programmiersprache ausgewählt sind, wird dieser Editor mit der korrekten Funktionsvorlage konfiguriert: '''Entferne oder bearbeite sie nicht!''' Platziere deinen Code innerhalb dieser Funktionssignatur. Falls du Hilfsfunktionen benötigst, kannst du diese einfach in deiner Hauptfunktionsdeklaration deklarieren. <span id="Using_input_types_in_your_code"></span> === Verwendung von Eingabetypen in deinem Code === Die Wikifunctions-Typen {{Z|Z6}} und {{Z|Z40}} können in JavaScript und Python3 wie native Typen verwendet werden. Beispielsweise lässt sich eine Zeichenkette verketten oder ein boolescher Wert direkt in einem logischen Ausdruck verwenden. Um andere Typen in deinen Code-Implementierungen zu verwenden, musst du den jeweiligen Typ genauer untersuchen, herausfinden, ob eine Umwandlung in ein natives Äquivalent existiert, und ihn entsprechend behandeln. Nehmen wir beispielsweise an, wir möchten Python-Code schreiben, der eine Eingabe vom Typ {{Z|Z20420}} verarbeitet. Auf der Seite für diesen Typ sehen wir uns die "Typumwandler in Code" an und suchen nach einem Python-Umwandler. Der Umwandler {{Z|Z20424}} wird auf unsere Datumseingabe angewendet, bevor unser Code ausgeführt wird. Unter "nativer Typ" sehen wir, dass unsere Eingabe ein Python-Dictionary ist, und in der Implementierung können wir die zu erwartenden Schlüssel sehen: <syntaxhighlight lang="python3"> return { 'K1': year, 'K2': month, 'K3': day } </syntaxhighlight> Wenn ein Typ keinen Umwandler besitzt, musst du direkt über seine Schlüssel auf seine Bestandteile zugreifen. Nehmen wir beispielsweise an, deine Funktion <code>Z30000</code> hat einen Eingabeparameter <code>Z30000K1</code> vom Typ {{Z|Z11}}. Dieser Typ besitzt zwei Schlüssel: <code>Z11K1</code> für die Sprache (selbst ein Objekt vom Typ {{Z|Z60}}) und <code>Z11K2</code> für den Zeichenketten-Wert. Das Sprachobjekt hat wiederum einen Schlüssel <code>Z60K1</code> für den Sprachcode. Um also eine Zeichenkette mit dem Sprachcode und dem Text zu erhalten, kannst du folgendes schreiben: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1 ) { // z. B. "de: beliebiger Text" return Z30000K1.Z11K1.Z60K1 + ": " + Z30000K1.Z11K2; } </syntaxhighlight> Für eine Kurzübersicht der verfügbaren Typumwandlungen besuche [[Special:MyLanguage/Wikifunctions:Execution targets#Default type conversion|die Tabelle der Standard-Typumwandlungen]]. <span id="Returning_the_right_outputs"></span> === Rückgabe der richtigen Ausgaben === Ähnlich wie bei der Behandlung von Eingaben müssen auch Ausgaben dem in der Funktionsdefinition angegebenen Typ entsprechen. Einige können wie native Typen behandelt werden; daher wird jede Zeichenketten-Ausgabe in ein Wikifunctions-Objekt {{Z|Z6}} und jeder von deiner Implementierung zurückgegebene native boolesche Wert in ein Wikifunctions-Objekt {{Z|Z40}} umgewandelt. Typen mit "Typumwandlern aus Code" wenden die entsprechende Funktion auf die Ausgabe an, um den benötigten Typ zu erzeugen. Am Beispiel von {{Z|Z20420}} transformiert {{Z|Z20443}} die Ausgabe deiner Implementierung – ein Dictionary mit den Schlüsseln K1, K2 und K3 – in die korrekte ZObjekt-Darstellung. Für Typen, die keine Umwandler aus Code haben, kannst du die Ausgabeobjekte sorgfältig erstellen und zurückgeben. Stell dir beispielsweise vor, unsere Funktion <code>Z30000</code> nimmt zwei Zeichenketten als Eingaben entgegen: Sprachcode und Text, und soll ein Objekt {{Z|Z11}} zurückgeben. In Python kannst du dies mit dem Konstruktor <code>ZObject</code> erreichen: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): lang_object = ZObject( {"Z1K1": "Z9", "Z9K1": "Z60"}, Z60K1 = Z30000K1 ) return ZObject( {"Z1K1": "Z9", "Z9K1": "Z11"}, Z11K1 = lang_object, Z11K2 = Z30000K2 ) </syntaxhighlight> Oder in JavaScript: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1, Z30000K2 ) { const langObject = new ZObject( new Map( [ [ "Z60K1", Z30000K1 ] ] ), { "Z1K1": "Z9", "Z9K1": "Z60" } ); const monolingualKeys = new Map( [ [ "Z11K1", langObject ], [ "Z11K2", Z30000K2 ] ] ); return new ZObject( monolingualKeys, { "Z1K1": "Z9", "Z9K1": "Z11" } ); } </syntaxhighlight> Du kannst mehr über die Klasse <code>ZObject</code> und andere nützliche Konstruktoren auf {{ll|Wikifunctions:Execution_targets#Custom_and_non-built-in_type_conversion}} erfahren. {{phab|T392750}}Stand Mai 2026 kann der Versuch, eine Liste von Listen zurückzugeben, fehlschlagen; daher ist es nicht möglich, solche Funktionen in Code zu implementieren. === Code in Python === In diesem Abschnitt geben wir ein konkretes Beispiel, wie man eine Implementierung in Form von Code in Python erstellt. Angenommen, wir möchten eine Implementierung für eine Funktion erstellen, die zwei Eingabezeichenketten durch Einfügen eines Leerzeichens dazwischen kombiniert und das Ergebnis zurückgibt. Nehmen wir an, die ZID dieser Funktion ist Z30000. Die Implementierung wird über die ZID der Funktion definiert. Das gilt auch für die Argumente der Funktion. Im Fall der Funktion Z30000 mit ihren beiden Argumenten sollte die Funktionsvorlage also so aussehen: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): </syntaxhighlight> Wie bereits erwähnt, wissen wir, dass die Argumente (<code>Z30000K1</code> und <code>Z30000K2</code>) Zeichenketten sind, daher können wir sie genauso behandeln wie native Zeichenketten in Python. Die Funktion sollte außerdem eine Zeichenkette zurückgeben. In unserem Beispiel geben wir einfach die beiden Argumente, getrennt durch ein Leerzeichen, aneinandergereiht zurück: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): return Z30000K1 + " " + Z30000K2 </syntaxhighlight> Da es sich um Python handelt, vergesse nicht, diese Zeile einzurücken. Wenn du unserem Rat gefolgt bist, [[#Practice Test-Driven Development|TDD anzuwenden]], verfügst du bereits über eine Reihe von Tests, von denen du weißt, dass sie funktionieren sollten. In diesem Fall kannst du während der Entwicklung deiner Implementierung auf den kreisförmigen Pfeil im Testbereich klicken und überprüfen, ob deine Implementierung alle Tests besteht. Denke daran, dass die Laufzeit keinen Status hat. Gehe nicht von Werten für globale oder statische Variablen aus. Wenn du weitere Fragen dazu hast, was du in Python tun kannst und was nicht, frage auf [[Wikifunctions:Python implementations]]. === Code in JavaScript === In diesem Abschnitt geben wir ein konkretes Beispiel, wie man eine Implementierung in Form von Code in JavaScript erstellt. Angenommen, wir möchten eine Implementierung für eine Funktion erstellen, die zwei Eingabezeichenketten durch Einfügen eines Leerzeichens dazwischen kombiniert und das Ergebnis zurückgibt. Nehmen wir an, die ZID dieser Funktion ist <code>Z30000</code>. Die Implementierung wird über die ZID der Funktion definiert. Das gilt auch für die Argumente der Funktion. Im Fall der Funktion <code>Z30000</code> mit ihren beiden Argumenten sollte die Funktionsvorlage also so aussehen: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1, Z30000K2 ) { } </syntaxhighlight> Wir wissen, dass die Argumente (<code>Z30000K1</code> und <code>Z30000K2</code>) Zeichenketten sind, daher können wir sie in JavaScript wie native Zeichenketten behandeln. Die Funktion soll außerdem eine Zeichenkette zurückgeben. Um die Funktion zu vervollständigen, kannst du eine Zeile hinzufügen, die die Eingabezeichenketten verkettet, etwa so: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1, Z30000K2 ) { return Z30000K1 + " " + Z30000K2; } </syntaxhighlight> Wenn du Tests wie im Abschnitt [[#Practice Test-Driven Development|TDD]] oben empfohlen hast, klicke auf den kreisförmigen Pfeil im Testbereich und prüfe, ob deine Implementierung alle Tests besteht. Denke daran, dass die Laufzeit keinen Status hat. Gehe nicht von Werten für globale oder statische Variablen aus. Wenn du weitere Fragen dazu hast, was du in JavaScript tun kannst und was nicht, frage auf [[Wikifunctions:JavaScript implementations]]. <span id="Calling_another_Wikifunctions_function"></span> === Aufruf einer anderen Wikifunctions-Funktion === Eine Code-Implementierung kann bestimmte andere Wikifunctions-Funktionen aufrufen, die Ausgabe des Aufrufs empfangen und diese Ausgabe für die weitere Verarbeitung nutzen. Wir bezeichnen solche Aufrufe als Callbacks. Derzeit können aus Sicherheits- und Leistungsgründen nur die folgenden integrierten Wikidata-Abruf- und Suchfunktionen auf diese Weise aufgerufen werden: {{Z|Z6820}}, {{Z|Z6821}}, {{Z|Z6822}}, {{Z|Z6824}}, {{Z|Z6825}}, {{Z|Z6826}}, {{Z|Z6830}} und {{Z|Z6831}}. Diese Funktionalität befindet sich in einem frühen Stadium der Einführung; wir hoffen, in Zukunft Aufrufe für eine größere Bandbreite an Funktionen zu ermöglichen. Betrachten wir eine JavaScript-Implementierung, die einen Callback enthält. Diese Implementierung ruft ein Datenobjekt von Wikidata ab, extrahiert die Bezeichnung dieses Datenobjektes in einer bestimmten Sprache und gibt die Bezeichnung als Zeichenkette zurück. Das abzurufende Datenobjekt wird über das Argument <code>Z400K1</code> angegeben, die Sprache über <code>Z400K2</code>. <syntaxhighlight lang="javascript"> function Z400( Z400K1, Z400K2 ) { const item = Wikifunctions.Call('Z6821', Z400K1); for (const label of item.Z6001K2.Z12K1) { if (label.Z11K1.Z60K1 === Z400K2.Z60K1) { return label.Z11K2; }} return 'NOT FOUND'; } </syntaxhighlight> Ein Callback wird durch den Aufruf von <code>Wikifunctions.Call</code> ausgelöst, wie im Beispiel gezeigt. Das erste Argument für <code>Wikifunctions.Call</code> ist stets die ZID der aufzurufenden Funktion – in diesem Fall {{Z|Z6821}}, welche ein einzelnes Argument entgegennimmt. Darauf folgen, durch Kommas getrennt, die an diese Funktion zu übergebenden Argumente. Hierbei handelt es sich bei dem Argument <code>Z400K1</code> um denselben Wert, der auch an <code>Z400</code> übergeben wurde. Dies ist ein gängiges Muster für die Argumentübergabe an Callbacks, jedoch können die Argumente auch mit dem Konstruktor <code>ZObject</code> (wie oben beschrieben) erstellt oder auf andere Weise bezogen werden. Der Wert von <code>Z400K1</code> wäre eine Instanz von {{Z|Z6091}}, die die QID des abzurufenden Datenobjekts enthält. Zeile 2 des Beispiels ruft <code>Z6821</code> auf, um dieses Datenobjekt von Wikidata abzurufen, und weist das resultierende ZObjekt der Konstante <code>item</code> zu. Der restliche Code durchläuft die Bezeichnungen des Datenobjekts, bis er diejenige findet, die der durch <code>Z400K2</code> angegebenen Sprache entspricht. Für das obige Beispiel haben wir der Einfachheit halber <code>Z6821</code> verwendet. Sofern die Implementierung jedoch nicht das gesamte Objekt benötigt, wird dringend empfohlen, zum Abrufen von Wikidata-Datenobjekten, die sehr groß sein können, <code>Z6820</code> zu verwenden. Obwohl der Aufruf von <code>Z6820</code> etwas komplexer ist, ermöglichen seine Parameter das Abrufen spezifischer Teile eines Wikidata-Datenobjekts. Dies kann die Leistung erheblich steigern und bestimmte Fehler vermeiden, da weniger Netzwerkbandbreite und Verarbeitungszeit erforderlich sind. (<code>Z6820</code> kann auch statt <code>Z6822</code>, <code>Z6824</code>, <code>Z6825</code> und <code>Z6826</code> verwendet werden, um ähnliche Vorteile bei der Bandweitenreduzierung zu erreichen.) Im Folgenden zeigen wir, wie <code>Z6820</code> in <code>Wikifunctions.Call</code> verwendet werden kann, um dasselbe Verhalten wie oben zu erzielen. Beachte, dass wir das zweite an <code>Z6820</code> übergebene Argument, <code>[labelsPart]</code>, nutzen, um festzulegen: “Gib nur die Bezeichnungen des Datenobjekts zurück”, und das dritte Argument, <code>[Z400K2]</code>, verwenden, um festzulegen: “Gib die Bezeichnungen nur in der angegebenen Sprache zurück”. (Dieses Argument würde auch für Aliasse und Beschreibungen gelten, sofern diese im Ergebnis enthalten wären.) <syntaxhighlight lang="javascript"> function Z400( Z400K1, Z400K2 ) { const labelsPart = new ZObject( new Map( [ ['Z6030K1', new ZReference('Z6033')] ] ), {Z1K1: 'Z9', Z9K1: 'Z6030'} ); const entities = Wikifunctions.Call( 'Z6820', [Z400K1], [labelsPart], [Z400K2], []); const item = entities.get(Z400K1.Z6091K1); const labels = item.Z6001K2.Z12K1; for (const label of labels) { if (label.Z11K1.Z60K1 === Z400K2.Z60K1) { return label.Z11K2; }} return 'NOT FOUND'; } </syntaxhighlight> Weitere zu beachtende Hinweise: * Obwohl Code-Implementierungen mittlerweile in der Lage sind, Wikidata-Entitäten abzurufen, wird empfohlen, dass sie keine ''vollständigen'' Entitäten zurückgeben. Dies liegt an den derzeitigen Beschränkungen hinsichtlich der Größe des von einer Code-Implementierung zurückgegebenen Wertes. Um eine vollständige, große Entität abzurufen und zurückzugeben, ist es besser, die Abruffunktion aus einer Komposition heraus aufzurufen. * Es kann nur ein Callback gleichzeitig ausgeführt werden. Aus Sicherheitsgründen ist es nicht möglich, die Nebenläufigkeitsfunktionen von JavaScript oder Python zu nutzen, um mehrere Callbacks parallel auszuführen. ** Beachte jedoch, dass du mithilfe von Z6820 mehrere Entitäten auf einmal abrufen kannst. * Derzeit gibt es eine Obergrenze von 3 MiB für die Größe von Wikidata-Inhalten, die über einen einzelnen Callback an eine Code-Implementierung zurückgegeben werden können. Dieselbe Obergrenze gilt für die Größe des Ergebnisses, das von einer Code-Implementierung zurückgegeben wird. <span id="Compositions"></span> == Kompositionen == Im diesem Abschnitt geben wir ein konkretes Beispiel, wie man eine Implementierung in Form einer Komposition erstellt. Angenommen, wir möchten eine Implementierung für eine Funktion erstellen, die zwei Eingabezeichenketten durch Einfügen eines Leerzeichens dazwischen kombiniert und das Ergebnis zurückgibt. Nehmen wir an, die ZID dieser Funktion ist <code>Z30000</code>. Normalerweise ist es sinnvoll, zunächst darüber nachzudenken, wie man vorhandene Funktionen kombinieren kann, um die gewünschte Ausgabe zu erzielen. Manchmal mag dies trivial sein und du kannst einfach mit dem Zusammenstellen und Funktionen fortfahren, aber in vielen Fällen lohnt es sich, die gewünschte Komposition zu notieren. Beispielsweise könnten wir für die angegebene Funktion die vorhandene Funktion {{Z|Z10000}} verwenden. Diese Funktion nimmt zwei Zeichenketten und erstellt daraus eine Zeichenkette. Aber wir müssen dazwischen ein Leerzeichen einfügen. Wir verbinden also zunächst ein Leerzeichen mit dem Ende der ersten Zeichenkette und verbinden dann die zweite Zeichenfolge mit dem Ergebnis dieser ersten Verbindung. Unsere Komposition könnte also so notiert werden: <syntaxhighlight lang="prolog"> join_strings( join_strings( Z30000K1, " " ), Z30000K2 ) </syntaxhighlight> Es gibt mehrere Möglichkeiten, eine Komposition zu schreiben: Beachte, dass dasselbe auch auf folgende Weise erreicht werden kann: <syntaxhighlight lang="prolog"> join_strings( Z30000K1, join_strings( " ", Z30000K2 ) ) </syntaxhighlight> Eine alternative Implementierung könnte auch die vorhandene Funktion {{Z|Z15175}} verwenden, sodass deine Komposition wie folgt aussehen könnte: <syntaxhighlight lang="prolog"> join_with_separator( Z30000K1, Z30000K2, " " ) </syntaxhighlight> Wie du siehst, gibt es mehrere Möglichkeiten, dies zu erreichen. Nimm dir also Zeit und erkunde die vorhandenen Funktionen, die im {{ll|Wikifunctions:Catalogue}} verfügbar sind. Versuchen wir, das zweite Beispiel zu erstellen, <code>join_strings(Z30000K1, join_strings(" ", Z30000K2))</code>. Um dies zu erstellen: # Um eine Implementierung hinzuzufügen, klicke auf der Funktionsseite in der Tabelle "Implementierungen" auf die Schaltfläche "+". # Stelle sicher, dass die Option "Komposition" unter "Implementierung" ausgewählt ist. # Klicke auf das Symbol "›" oder auf den Link "Funktion auswählen", um die Funktionsdetails anzuzeigen. # Suche unter "Funktion" nach dem Namen der äußersten Funktion, die du verwenden möchtest, in diesem Beispiel "verbinde Zeichenketten". Wähle anschließend die gewünschte Funktion aus der Dropdown-Liste aus. # Du siehst zwei neue Felder, eines für jedes der Argumente, die für die ausgewählte Funktion benötigt werden. # Als erstes Argument möchten wir den ersten Eingabewert für unsere Funktion auswählen: ## Klicke neben "erste Zeichenkette" auf die Schaltfläche "…" und wähle "Argumentreferenz" aus. ## Unter "Schlüssel-ID" kannst du nun die erste Zeichenkette deiner Funktion aus dem Dropdown-Menü auswählen, das alle verfügbaren Eingaben enthält. # Für das zweite Argument möchten wir das Ergebnis eines weiteren Aufrufs von "verbinde Zeichenketten" verwenden: ## Klicke neben "zweite Zeichenkette" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus. ## Suche unter "Funktion" nach der Funktion, die du aufrufen möchtest und wähle sie aus, nämlich "verbinde Zeichenketten". ## Konfiguriere die "erste Zeichenkette" für diesen inneren Funktionsaufruf, indem du einfach ein Leerzeichen in das Textfeld eingibst, und konfiguriere die "zweite Zeichenkette" wie in Schritt 6: Ändere sie mit der Schaltfläche "…" in "Argumentreferenz" und wähle dann das zweite Argument in der Dropdown-Liste aus. Deine Komposition ist nun fertig! Du kannst die Details mithilfe der Pfeiltasten ein- und ausblenden, um dir einen Überblick zu verschaffen. Falls du bereits Tests wie im Abschnitt [[#Practice Test-Driven Development|TDD]] oben empfohlen implementiert hast, klicke im Testbereich auf den kreisförmigen Pfeil und prüfe, ob deine Implementierung die Tests besteht. Sobald deine Komposition die Tests bestanden hat, kannst du sie veröffentlichen. [[File:Composition implementation expanded.png|frame|center|alt=Eine Wikifunctions-Kompositionsimplementierung in ihrer erweiterten Ansicht|Eine Wikifunctions-Kompositionsimplementierung in ihrer erweiterten Ansicht]] [[File:Composition implementation collapsed.png|frame|center|alt=Eine Wikifunctions-Kompositionsimplementierung in ihrer reduzierten Ansicht|Eine Wikifunctions-Kompositionsimplementierung in ihrer reduzierten Ansicht]] <span id="Wikifunctions_error_handling"></span> == Fehlerbehandlung auf Wikifunctions == Als Ersteller einer Wikifunctions-Funktion möchtest du möglicherweise den Benutzer warnen, der deine Funktion aufruft, wenn im Code ein Fehler auftritt oder seine Eingaben bestimmte Kriterien nicht erfüllen. Wenn deine Funktion beispielsweise eine Zeichenkette mit einem Namen erwartet, solltest du prüfen, ob der Name nicht leer ist, und gegebenenfalls eine verständliche Fehlermeldung anzeigen. Hierfür kannst du <code>Wikifunctions.Error()</code> in deinen Code-Implementierungen oder die Funktion {{Z|Z851}} in deinen Kompositionen verwenden. In diesem Abschnitt erfährst du: * Wie man Fehler sowohl aus Code- als auch aus Kompositions-Implementierungen auslöst, * wie man Tests für Fehlerfälle schreibt, und * wie man Fehler abfängt und behandelt, die von Funktionen ausgelöst werden, die man in seinen Kompositionen verwendet. <span id="Throwing_errors_from_code_implementations"></span> === Fehler aus Code-Implementierungen auslösen === Sowohl beim Schreiben von JavaScript- als auch von Python-Code kannst du <code>Wikifunctions.Error()</code> nutzen, um die Ausführung mit einem gewünschten Fehler zu beenden. <code>Wikifunctions.Error()</code> hat zwei Parameter: # Fehlertyp: Eine Zeichenkette, die die ZID des Fehlertyps enthält, den du zurückgeben möchtest. # Fehlerargumente: Eine Liste von Zeichenkettenargumenten zur Erstellung des Fehlers. Gehen wir sie der Reihe nach durch: <span id="Error_type"></span> ==== Fehlertyp ==== Ein Fehlertyp ist ein Objekt, das eine Art von Fehler beschreibt, der im System auftreten kann. Es gibt eine Reihe vordefinierter Fehlertypen, du kannst aber auch eigene Fehlertypen erstellen, die besser zu deinem Anwendungsfall passen. Bei der Verwendung von Fehlern empfiehlt es sich, die verfügbaren Fehlertypen zu durchsuchen, die sich in [[Special:ListObjectsByType/Z50|dieser Liste]] finden. Falls keine passenden Fehler für deinen Fall vorhanden sind, erstelle einen neuen Fehler, indem du zur Erstellungsseite gehst und im Typauswahlfeld "Fehlertyp" auswählst. Lege anschließend die erforderlichen Felder fest: [[File:Error type.png|thumb|alt=Erstellung von Fehlertypen in Wikifunctions|Um einen neuen Fehlertyp (Z50) zu erstellen, bearbeite die Bezeichnung und füge die erforderlichen Schlüssel hinzu.]] * '''Bezeichnung''' – Dies ist der Haupttitel des Fehlers, der eine kurze, aber aussagekräftige Meldung enthalten sollte. Lege die Fehlerbezeichnung im rechten Feld mit dem Titel "Info" fest. * '''Schlüssel''' – Schlüssel enthalten zusätzliche Informationen zur Fehlerursache. Wenn beispielsweise eine Eingabe das falsche Format aufwies, möchtest du den Benutzer möglicherweise über den eingegebenen Inhalt informieren, wenn der Fehler auftritt. Um sie in deinen Implementierungen zu verwenden, müssen Schlüssel vom Zeichenketten sein. Um einen Schlüssel zu erstellen, klicke auf das Symbol "[+]" unterhalb von "Schlüssel", wähle unter "Werttyp" die Option "Zeichenkette" aus und füge eine aussagekräftige Bezeichnung hinzu, beispielsweise "tatsächlich Eingabe". Sobald du alle erforderlichen Schlüssel erstellt hast, kannst du deinen Fehlertyp veröffentlichen und die ID des neu erstellten Objekts speichern. * '''Fehlermeldung''' – Fehlertypen können ein mehrsprachiges Array von Fehlermeldungen enthalten, die mit HTML-Parametern versehen sind. Die Parameter werden als $1, $2 etc. angegeben, wobei die Ziffer dem Schlüssel des Fehlertyps entspricht. Beim Erstellen eines Fehlertyps mit dem Zeichenketten-Schlüssel "aktuelle Eingabe", kann die Fehlermeldung beispielsweise den Platzhalter "$1" verwenden, der zum Zeitpunkt der Fehlerausgabe durch den Wert des Schlüssels "aktuelle Eingabe" ersetzt wird. Um HTML-Meldungen hinzuzufügen, klicke unter "HTML-Fragmente" auf das Symbol "[+]", wähle eine Sprache aus und gib die HTML-Zeichenkette ein. <span id="Error_arguments"></span> ==== Fehlerargumente ==== Fehlerargumente entsprechen den Schlüsseln des Fehlertyps und sollten zusätzliche Informationen zum Verständnis des Fehlers liefern. Fehlerargumente sollten immer Zeichenketten sein. <span id="Using_Wikifunctions.Error()"></span> ==== Verwendung von Wikifunctions.Error() ==== Angenommen, du möchtest einen Fehler auslösen, wenn entweder deine erste oder deine zweite Eingabe leer ist. Du hast den Fehlertyp bereits erstellt und ihm wurde die ZID <code>Z30005</code> zugewiesen. Dein Fehlertyp hat zwei Zeichenketten-Schlüssel: * Eingabeschlüssel: Enthält den Schlüssel der fehlerhaften Eingabe * Eingabewert: Enthält den aktuellen Wert der fehlerhaften Eingabe Um einen Fehler in deiner JavaScript-Implementierung auszulösen, solltest du etwa Folgendes tun: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1, Z30000K2 ) { if ( trim( Z30000K1 ) === '' ) { // Wenn die erste Eingabe leer ist, löse Fehler Z30005 aus // mit zwei Zeichenketten-Argumenten: [ erster Eingabe-Schlüssel, erster Eingabe-Wert ] Wikifunctions.Error( 'Z30005', [ "Z30000K1", Z30000K1 ] ) } if ( trim( Z30000K2 ) === '' ) { // Wenn die zweite Eingabe leer ist, löse Fehler Z30005 aus // mit zwei Zeichenketten-Argumenten: [ zweiter Eingabe-Schlüssel, zweiter Eingabe-Wert ] Wikifunctions.Error( 'Z30005', [ "Z30000K2", Z30000K2 ] ) } return Z30000K1 + " " + Z30000K2; } </syntaxhighlight> Um einen Fehler in deiner Python-Implementierung auszulösen, solltest du etwa Folgendes tun: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): if Z30000K1.strip() == "": # Wenn die erste Eingabe leer ist, löse Fehler Z30005 aus # mit zwei Zeichenketten-Argumenten: [ erster Eingabe-Schlüssel, erster Eingabe-Wert ] Wikifunctions.Error("Z30005", ["Z30000K1", Z30000K1]) if Z30000K2.strip() == "": # Wenn die zweite Eingabe leer ist, löse Fehler Z30005 aus # mit zwei Zeichenketten-Argumenten: [ erster Eingabe-Schlüssel, erster Eingabe-Wert ] Wikifunctions.Error("Z30005", ["Z30000K2", Z30000K2]) return Z30000K1 + " " + Z30000K2 </syntaxhighlight> Denke daran, dass der Aufruf von <code>Wikifunctions.Error()</code> die Ausführung beendet! <span id="Throwing_errors_from_compositions"></span> === Fehler aus Kompositionen auslösen === Wenn du eine Kompositionsimplementierung erstellst, kannst du einen Fehler auslösen, indem du die Spezialfunktion {{Z|Z851}} aufrufst. <span id="Throw_Error_function_(Z851)"></span> ==== Funktion Fehler auslösen (Z851) ==== Die Funktion {{Z|Z851}} ähnelt der Methode <code>Wikifunctions.Error()</code> und benötigt zwei Argumente: * '''Fehlertyp''' – Ein Verweis auf den Fehlertyp, den du auslösen möchtest * '''Fehlerparameter''' – Eine Liste mit den Argumenten zur Erstellung deines Fehlers, die ebenfalls Zeichenketten sein sollten. <span id="Using_Throw_Error"></span> ==== Verwendung von Fehler auslösen ==== Angenommen, du möchtest deine Komposition so ändern, dass sie zuerst prüft, ob die Argumente nicht leer sind, und einen Fehler ausgibt, wenn sie ein leeres Argument findet. Wenn dann keines der Argumente leer ist, wird die ursprüngliche Komposition ausgeführt, die wie folgt aussieht: <syntaxhighlight lang="prolog"> join_with_separator( Z30000K1, Z30000K2, " " ) </syntaxhighlight> Dazu musst du bedingte Pfade erstellen, für die du die Funktion {{Z|Z802}} verwenden kannst. Stell es dir folgendermaßen vor: * Wenn das erste Argument leer ist, soll ein Fehler für das erste Argument ausgelöst werden * Andernfalls wird mit der Überprüfung des zweiten Arguments fortgefahren * Wenn das zweite Argument leer ist, soll ein Fehler für das zweite Argument ausgelöst werden * Andernfalls wird der Erfolgspfad verfolgt und die verbundenen Zeichenketten mit dem Leerzeichen als Trennzeichen zurückgegeben Oder in funktionalem Pseudocode: <syntaxhighlight lang="prolog"> if ( is_empty_string( Z30000K1 ), throw_error( Z30005, [ "Z30000K1", Z30000K1 ] ), if( is_empty_string( Z30000K2 ), throw_error( Z30005, [ "Z30000K2", Z30000K2 ] ), join_with_separator( Z30000K1, Z30000K2, " " ) ) ) </syntaxhighlight> Lass uns das Schritt für Schritt erstellen: # Um eine Implementierung hinzuzufügen, klicke auf der Funktionsseite in der Tabelle "Implementierungen" auf die Schaltfläche "+". # Stelle sicher, dass die Option "Komposition" unter "Implementierung" ausgewählt ist. # Klicke auf das Symbol "›" oder auf den Link "Funktion auswählen", um die Funktionsdetails anzuzeigen. # Suche unter "Funktion" nach der äußersten Funktion, die du verwenden möchtest, in diesem Fall "wenn", und wähle sie aus. # Überprüfe die Gültigkeit des ersten Arguments: ## Klicke neben "Bedingung" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "ist leere Zeichenkette" und wähle sie aus ## Klicke neben "Eingabe" auf die Schaltfläche "…" und wähle "Argumentreferenz" aus ## Wähle unter "Schlüssel-ID" die erste Eingabe aus (z. B. "erste Zeichenkette") ## Du kannst den Funktionsaufruf der "Bedingung" nun bei Bedarf ausblenden, indem du auf den Pfeil nach unten neben "Bedingung" klickst. Es sollte dann etwa Folgendes angezeigt werden: "f(x) ist leere Zeichenkette ( → erste Zeichenkette )" # Fehler auslösen, wenn die Bedingung wahr ist: ## Klicke neben "dann" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "Fehler auslösen" und wähle sie aus ## Suche unter "Fehlertyp" nach deinem Fehlertyp (du kannst die Fehler-ID direkt eingeben, wenn du sie kennst, z. B. Z30005) und wähle ihn aus ## Füge unter "Fehlerparameter" zwei Elemente hinzu, indem du auf die Schaltfläche "+" klickst ## Lege für "Objekt 1" (fehlerhafter Argumentschlüssel) den Typ auf "Zeichenkette" fest und trage die Argumentkennung ein (z. B. "erste Eingabe" oder "Z30000K1") ## Klicke für "Objekt 2" (fehlerhafter Argumentwert) auf die "…" neben "Objekt 2" und wähle "Argumentreferenz" aus ## Wähle unter "Schlüssel-ID" die erste Eingabe aus (z. B. "erste Zeichenkette") ## Du kannst den Funktionsaufruf "dann" nun bei Bedarf ausblenden, indem du auf den Pfeil nach unten neben "dann" klickst. Es sollte dann etwa Folgendes angezeigt werden: "f(x) Fehler auslösen ( ungültiges Format, typisierte Liste ( Objekt, "erste Eingabe", → erste Zeichenkette ) )" # Prüfe das zweite Argument, wenn das erste korrekt war: ## Klicke neben "sonst" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "wenn" und wähle sie aus ## Richte eine "Bedingung" ein, um die Gültigkeit des zweiten Arguments zu überprüfen, indem du das gleiche Verfahren wie in Schritt 5 beschrieben anwendest. ## Richte "dann" so ein, dass beim zweiten Argument ein Fehler ausgelöst wird, indem du das gleiche Verfahren wie in Schritt 6 beschrieben anwendest. # Richte schließlich den Erfolgspfad ein: ## Klicke neben dem verschachtelten "sonst" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der gewünschten Funktion, in diesem Fall "vereinige zwei Zeichenketten mit Trennzeichen", und wähle sie aus ## Klicke neben "erste Zeichenkette" auf die Schaltfläche "…" und setze sie auf "Argumentreferenz", wähle anschließend "erste Zeichenkette" aus ## Klicke neben "zweite Zeichenkette" auf die Schaltfläche "…" und setze sie auf "Argumentreferenz", wähle anschließend "zweite Zeichenkette" aus ## Füge unter "Trennzeichen" ein Leerzeichen in das Textfeld ein Der resultierende Funktionsaufruf sollte folgendermaßen aussehen: [[File:Throw error expanded.png|frame|center|alt=Wikifunctions-Komposition mit der Funktion Fehler auslösen|Wikifunctions-Komposition mit der Funktion Fehler auslösen]] [[File:Throw error collapsed.png|frame|center|alt=Wikifunctions-Komposition mit der Funktion Fehler auslösen in ihrer reduzierten Ansicht|Wikifunctions-Komposition mit der Funktion Fehler auslösen in ihrer reduzierten Ansicht]] <span id="Handling_errors_in_compositions"></span> === Fehlerbehandlung in Kompositionen === Es ist zwar nützlich, Funktionen das Auslösen erwarteter Fehler zu ermöglichen, aber es ist entscheidend, Fehler in den eigenen Kompositionen behandeln zu können, um diese Funktionen sicher verwenden zu können. Angenommen, du möchtest eine neue Funktion "vollständiger Name einer Person" erstellen – wir bezeichnen sie mit der ZID <code>Z30010</code>. Diese Funktion soll den vollständigen Namen einer Person anhand ihres Vor- und Nachnamens zurückgeben. Ist jedoch eines der beiden Felder leer, soll sie stattdessen den Text "Unbekannt" zurückgeben. Du könntest eine Komposition erstellen, indem du unsere Beispielfunktion "verbinde zwei Zeichenketten mit Leerzeichen" oder <code>Z30000</code> verwendest, um den Namen zu generieren. Wenn eine der Eingaben leer ist, weißt du, dass <code>Z30000</code> einen Fehler vom Typ <code>Z30005</code> auslöst. Mithilfe der Funktion {{Z|Z850}} als Wrapper kannst du die Verbindungsoperation ausführen und einen möglichen Fehler abfangen, indem du einfach "Unbekannt" zurückgibst, wenn er auftritt. <span id="Try-Catch_function_(Z850)"></span> ==== Try-Catch-Funktion (Z850) ==== Die Funktion {{Z|Z850}} ist eine integrierte Funktion mit der ZID <code>Z850</code> und benötigt drei Argumente: * '''Funktionsaufruf''' – Der erste Funktionsaufruf, der ausgeführt werden soll. Wenn kein Fehler auftritt, ist die Antwort das Ergebnis dieses Funktionsaufrufs. * '''Fehlertyp''' – Ein Fehlertyp, der abgefangen werden soll, falls er während der Ausführung des ersten Funktionsaufrufs auftritt. * '''Fehlerhandler''' – Ein Funktionsaufruf, der ausgeführt wird, falls der oben genannte Fehler während der Ausführung des ursprünglichen Funktionsaufrufs auftritt. In diesem Fall wird das Ergebnis der Fehlerbehandlung zurückgegeben. <span id="Using_Try-Catch"></span> ==== Verwendung der Try-Catch-Funktion ==== Sobald wir alle Funktionen für unsere Komposition haben, können wir sie folgendermaßen gestalten: <syntaxhighlight lang="prolog"> try_catch( join_with_space( Z30010K1, Z30010K2 ), Z30005, echo( "Unknown" ) ) </syntaxhighlight> Das bedeutet: * Die Funktion "verbinde zwei Zeichenketten mit Leerzeichen" wird mit den beiden Eingaben ausprobiert und wenn alles erfolgreich verläuft, wird das Ergebnis dieser Funktion zurückgegeben * Wenn eine der Eingaben leer ist, löst "verbinde zwei Zeichenketten mit Leerzeichen" einen Fehler vom Typ <code>Z30005</code> aus * Unsere {{Z|Z850}} erkennt dann diesen Fehler und führt die Funktion {{Z|Z801}} aus, die "Unbekannt" zurückgibt Lass uns das Schritt für Schritt erstellen: # Um eine Implementierung hinzuzufügen, klicke auf der Funktionsseite in der Tabelle "Implementierungen" auf die Schaltfläche "+". # Stelle sicher, dass die Option "Komposition" unter "Implementierung" ausgewählt ist. # Klicke auf das Symbol "›" oder auf den Link "Funktion auswählen", um die Funktionsdetails anzuzeigen. # Suche unter "Funktion" nach der äußersten Funktion, die du verwenden möchtest, in diesem Fall "Try-Catch-Funktion", und wähle sie aus. # Richte den Hauptfunktionsaufruf ein: ## Klicke unterhalb des Feldes, in dem die "Try-Catch-Funktion" ausgewählt ist, neben dem Schlüssel "Funktionsaufruf" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "verbinde zwei Zeichenketten mit Leerzeichen" und wähle sie aus ## Klicke neben "erste Zeichenkette" auf die Schaltfläche "…" und wähle "Argumentreferenz" aus, wähle anschließend das Argument "erster Name" aus der Dropdown-Liste aus. ## Klicke neben "zweite Zeichenkette" auf die Schaltfläche "…" und wähle "Argumentreferenz" aus, wähle anschließend das Argument "zweiter Name" aus der Dropdown-Liste aus. # Wähle den abzufangenden Fehler aus: ## Suche unter "Fehlertyp" nach "ungültige Zeichenkette" und wähle es aus – du kannst direkt nach der ZID <code>Z30005</code> suchen # Richte den Funktionsaufruf für den Fehlerhandler ein: ## Klicke neben "Fehlerhandler" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "Echo" und wähle sie aus ## Suche unter "Eingabe" und "Typ" den Typ "Zeichenkette" und wähle ihn aus ## Gib nun unter "Eingabe" im Textfeld "Unbekannt" ein Die resultierende Funktion sollte folgendermaßen aussehen: [[File:Try catch expanded.png|frame|center|alt=Wikifunctions-Komposition mit der Try-Catch-Funktion in ihrer erweiterten Ansicht|Wikifunctions-Komposition mit der Try-Catch-Funktion in ihrer erweiterten Ansicht]] [[File:Try catch collapsed.png|frame|center|alt=Wikifunctions-Komposition mit der Try-Catch-Funktion in ihrer reduzierten Ansicht|Wikifunctions-Komposition mit der Try-Catch-Funktion in ihrer reduzierten Ansicht]] <span id="Testing_your_failure_use_cases"></span> === Testen deiner Fehlerfälle === Wie bereits im Abschnitt über die [[#Practice Test-Driven Development|Anwendung von TDD]] erläutert, ist es wichtig, nicht nur die häufigsten Ausführungspfade, sondern auch mögliche Randfälle zu testen. Ebenso wichtig ist es, das Fehlerverhalten zu prüfen. In diesem Abschnitt stellen wir dir die notwendigen Werkzeuge vor, um zu testen, ob deine Funktion bei bestimmten Eingaben fehlschlägt und ob die Fehlermeldung den Erwartungen entspricht. Dazu benötigst du zwei weitere Systemfunktionen: <span id="Is_error_type_(Z852)"></span> ==== ist Fehlertyp (Z852) ==== Die Funktion {{Z|Z852}} ist eine integrierte Funktion mit der ZID <code>Z852</code> und benötigt zwei Argumente: * '''Fehler''' – Ein {{Z|Z5}}-Objekt, das bei einem fehlgeschlagenen Aufruf ausgelöst werden kann. Eine Fehlerinstanz hat einen Typ und einen Wert. * '''Fehlertyp''' – Ein Verweis auf einen {{Z|Z50}}, der mit dem als erstes Argument übergebenen Fehlertyp verglichen wird. Ist dies der Fall, gibt die Funktion wahr zurück. <span id="Get_error_thrown_by_function_call_(Z853)"></span> ==== Fehler erhalten, ausgelöst durch Funktionsaufruf (Z853) ==== Die Funktion {{Z|Z853}} ist eine integrierte Funktion mit der ZID <code>Z853</code> und benötigt ein Argument: * '''Funktionsaufruf''' – Ein Funktionsaufruf, der entweder einen erfolgreichen Wert beliebigen Typs zurückgibt oder einen Fehler auslöst. Diese Funktion gibt ein {{Z|Z882}} zurück, wobei an erster Stelle ein {{Z|Z40}} und an zweiter Stelle ein {{Z|Z1}} steht: * Wenn der Funktionsaufruf erfolgreich ist und somit keinen Fehler auslöst, enthält das zurückgegebene Paar an erster Stelle falsch und an zweiter Stelle leer. * Wenn der Funktionsaufruf einen Fehler auslöst, enthält das zurückgegebene Paar an erster Stelle wahr und an zweiter Stelle den abgefangenen Fehler. Um diese Funktion in deinen Kompositionen zu verwenden, musst du möglicherweise die zusätzlichen Funktionen verwenden: * {{Z|Z821}} und * {{Z|Z822}} <span id="Testing_errors"></span> ==== Fehler testen ==== Angenommen, unsere Zielfunktion "verbinde zwei Zeichenketten mit Leerzeichen" oder <code>Z30000</code> löst einen Fehler vom Typ <code>Z30005</code> aus, und wir möchten dieses Verhalten testen. Dazu müssen wir Folgendes tun: * Einen fehlgeschlagenen Funktionsaufruf auslösen * Den Fehler mit der Funktion {{Z|Z853}} erhalten * Mit {{Z|Z852}} prüfen, ob der Fehler den richtigen Typ hat Tests haben zwei Felder: * '''Aufruf''' – Ein Funktionsaufruf, der mit den zu testenden Eingaben eine Ausgabe erzeugt. Dieser Aufruf gibt einen Wert zurück. * '''Ergebnisprüfung''' – Ein Funktionsaufruf, der überprüft, ob der vom vorherigen Aufruf zurückgegebene Wert dem erwarteten Wert entspricht. Das erste Argument dieses Funktionsaufrufs wird automatisch mit dem Rückgabewert des ersten Aufrufs belegt. Für eine Schritt-für-Schritt-Anleitung zum Erstellen von Tests siehe {{ll|Wikifunctions:Introduction#Create_tests}}. In unserem Beispiel können wir es so strukturieren — aber das ist nicht die einzige Möglichkeit! Der Aufruf, der ein {{Z|Z5}}-Objekt zurückgibt: <syntaxhighlight lang="prolog"> error = get_second_element_of_typed_list( get_error_thrown_by( join_strings_by_whitespace( "", "not empty" ) ) ) </syntaxhighlight> Und die Ergebnisprüfung, die das {{Z|Z5}}-Objekt als erstes Argument verwendet: <syntaxhighlight lang="prolog"> is_error_type( error, Z30005 ) </syntaxhighlight> Lass uns das Schritt für Schritt tun: # Um einen Test hinzuzufügen, klicke auf der Funktionsseite in der Tabelle "Tests" auf die Schaltfläche "+". Die Felder "Aufruf" und "Ergebnisprüfung" enthalten bereits vordefinierte Funktionen. Um die Fehler zu testen, müssen wir diese jedoch ändern. # Als Erstes richten wir den Aufruf ein: ## Klicke unter "Aufruf" auf die Schaltfläche "›", um den Funktionsaufruf zu erweitern. ## Bearbeite das Feld unter "Funktion" und suche die Funktion "erhalte zweites Element eines typisierten Paars" und wähle sie aus ## Klicke anschließend neben "typisiertes Paar" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "Fehler erhalten, ausgelöst durch Funktionsaufruf" und wähle sie aus ## Klicke neben "Funktionsaufruf" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "verbinde zwei Zeichenketten mit Leerzeichen" (oder nach ZID <code>Z30000</code>) und wähle sie aus ## Lege nun die Eingaben so fest, dass ein Fehler auftritt: Mindestens eine von ihnen muss leer sein. ## Du kannst jetzt deinen "Aufruf" durch erneutes Klicken auf den Pfeil nach unten wieder ausblenden, wenn du möchtest! # Als Nächstes richten wir die Ergebnisprüfung ein: ## Klicke unter "Ergebnisprüfung" auf die Schaltfläche "›", um den Funktionsaufruf zu erweitern. ## Bearbeite das Feld unter "Funktion" und suche die Funktion "ist Fehlertyp" und wähle sie aus ## Du wirst nun nur noch aufgefordert, das zweite Argument zu konfigurieren. Suche unter "Fehlertyp" nach deinem Fehlertyp <code>Z30005</code> und wähle ihn aus. # Und du bist fertig! Du kannst jetzt auf den kreisförmigen Pfeil im Feld "Implementierungen" klicken und solltest grüne Häkchen sehen. Wenn alles geklappt hat, kannst du deinen Test jetzt speichern. Er sollte folgendermaßen aussehen: [[File:Get error expanded.png|frame|center|alt=Testen eines Fehlers mit den Funktionen Fehler erhalten und ist Fehlertyp in ihrer erweiterten Ansicht|Testen eines Fehlers mit den Funktionen Fehler erhalten und ist Fehlertyp in ihrer erweiterten Ansicht]] [[File:Get error collapsed.png|frame|center|alt=Testen eines Fehlers mit den Funktionen Fehler erhalten und ist Fehlertyp in ihrer reduzierten Ansicht|Testen eines Fehlers mit den Funktionen Fehler erhalten und ist Fehlertyp in ihrer reduzierten Ansicht]] <span id="Creating_actionable_error_messages"></span> === Erstellung handlungsorientierter Fehlermeldungen === Wie oben beschrieben, verfügen Fehlertypen über einen optionalen Schlüssel <code>Z50K3</code>, der eine mehrsprachige Liste von HTML-Zeichenketten enthält. Bei der Darstellung von Informationen zu einem Fehler können die im Fehlertyp hinterlegten Meldungen dazu beitragen, eine klare, präzise, ​​informative, übersetzbare und handlungsorientierte Fehlermeldung zu erstellen. Zu diesem Zweck können Fehlermeldungen Parameter wie <code>$1</code>, <code>$2</code> etc. enthalten, wobei die Ziffer dem Argument des Fehlertyps und dessen Wert in der Fehlerinstanz entspricht. Diese Fehlermeldungen werden in Wikifunctions nach der Ausführung eines Funktionsaufrufs im Dialogfenster "Details" angezeigt. Darüber hinaus werden diese Fehlermeldungen auch in anderen Client-Schnittstellen, wie der Abstrakten Wikipedia, ausgegeben, um den Autoren von Abstrakten Inhalten eine bessere Orientierung zu bieten. [[File:Wikifunctions actionable error message example in the Details dialog.png|thumb|<span lang="en" dir="ltr" class="mw-content-ltr">The error message is rendered using the HTML message of the error type and the error argument values.</span>]] [[File:Wikifunctions actionable error message example in Abstract Wikipedia.png|thumb|<span lang="en" dir="ltr" class="mw-content-ltr">When available, the HTML error message is rendered in the Abstract Wikipedia preview section.</span>]] <div lang="en" dir="ltr" class="mw-content-ltr"> Let's use a real example to understand the benefits of HTML error messages: </div> <div lang="en" dir="ltr" class="mw-content-ltr"> The function {{Z|Z37847}} returns the first Lexeme reference given a Wikidata Item reference and a language. When there is no Lexeme for this Item-Language combination, it throws an error of type {{Z|Z28248}}, which has three keys: </div> * <span lang="en" dir="ltr" class="mw-content-ltr">'''Z28248K1''' is the input Wikidata item QID</span> * <span lang="en" dir="ltr" class="mw-content-ltr">'''Z28248K2''' is the connecting property, in this case <code>P5137/item for this sense</code></span> * <span lang="en" dir="ltr" class="mw-content-ltr">'''Z28248K3''' is the language code</span> <div lang="en" dir="ltr" class="mw-content-ltr"> When calling this function for a Wikidata lexeme that doesn't exist, the call will throw an error instance like this: </div> <syntaxhighlight lang="json" highlight="10,12"> { "Z1K1": "Z5", "Z5K1": "Z28248", "Z5K2": { "Z1K1": { "Z1K1": "Z7", "Z7K1": "Z885", "Z885K1": "Z28248" }, "Z28248K1": "Q319", "Z28248K2": "P5137", "Z28248K3": "ast" } } </syntaxhighlight> <div lang="en" dir="ltr" class="mw-content-ltr"> While the error type label indicates: <code>No matching lexeme for item in language</code>, a better error message should indicate: </div> * <span lang="en" dir="ltr" class="mw-content-ltr">which is the failing item,</span> * <span lang="en" dir="ltr" class="mw-content-ltr">which is the language missing, and</span> * <span lang="en" dir="ltr" class="mw-content-ltr">what are the possible ways to fix it.</span> <div lang="en" dir="ltr" class="mw-content-ltr"> The error message <code>Z50K3</code> field can provide this functionality. Whenever an Error Type has an error message for the user language (or any of its fallbacks), the error message shown will be rendered by: </div> # <span lang="en" dir="ltr" class="mw-content-ltr">First, replacing the message parameters with the values of the keys. In our example, any <code>$1</code> will be replaced with the value of <code>Z28248K1</code> ("Q319"), <code>$2</code> with "P5137", and <code>$3</code> with "ast",</span> # <span lang="en" dir="ltr" class="mw-content-ltr">Last, sanitizing and rendering the HTML message.</span> <div lang="en" dir="ltr" class="mw-content-ltr"> So a HTML message like: </div> <syntaxhighlight lang="html"> There is no matching lexeme for the item $1 in "$3".<br> <a href="http://wikidata.org/wiki/$1">Edit in Wikidata</a> </syntaxhighlight> <div lang="en" dir="ltr" class="mw-content-ltr"> Will become: </div> : There is no matching lexeme for the item Q319 in "ast" : [[d:Q319|Edit in Wikidata]] <span id="Debugging_your_implementations"></span> == Debuggen deiner Implementierungen == Manchmal läuft etwas schief. Eine Funktion verhält sich möglicherweise anders als erwartet oder ein Wert erscheint merkwürdig. Implementierungen können mitunter sehr komplex sein, und da sie in einer Spielwiesen-Umgebung ausgeführt werden, kann die Fehlersuche extrem schwierig erscheinen. Um das Verständnis der Vorgänge innerhalb eines Funktionsaufrufs zu erleichtern, bietet Wikifunctions einige Debugging-Werkzeuge. Diese Werkzeuge verändern nicht das Ergebnis einer Funktion, sondern fügen den zurückgegebenen Metadaten zusätzliche Informationen hinzu, die du nach dem Ausführen der Funktion einsehen kannst. Du kannst <code>Wikifunctions.Debug()</code> in deinen Code-Implementierungen oder die Funktion {{Z|Z854}} in deinen Kompositionen verwenden. In diesem Abschnitt erfährst du: * Wie man Debug-Meldungen sowohl aus Code- als auch aus Kompositions-Implementierungen hinzufügt, * Wie man die Metadaten manuell oder über die Benutzeroberfläche untersucht, um diese Protokolle einzusehen. <span id="Debugging_your_code_implementations"></span> === Debuggen deiner Code-Implementierungen === Beim Schreiben von Code, sowohl in JavaScript als auch in Python3, kannst du <code>Wikifunctions.Debug()</code> verwenden, um eine Meldung zu deinem Debug-Protokoll hinzuzufügen und die Ausführung fortzusetzen. {{phab|T441028}} <code>Wikifunctions.Debug()</code> hat einen Parameter, der üblicherweise als Zeichenkette erwartet wird. Jedes andere als Parameter übergebene Objekt wird jedoch direkt in eine Zeichenkette umgewandelt. Um zu unseren Code-Implementierungen für unsere Beispielfunktion "verbinde zwei Zeichenketten mit Leerzeichen" Debug-Protokolle hinzuzufügen, können wir dies in JavaScript tun: <syntaxhighlight lang="JavaScript"> function Z30000( Z30000K1, Z30000K2 ) { if ( trim( Z30000K1 ) === '' ) { Wikifunctions.Debug( `first input is empty "${ Z30000K1 }"` ); Wikifunctions.Error( 'Z30005', [ "Z30000K1", Z30000K1 ] ) } if ( trim( Z30000K2 ) === '' ) { Wikifunctions.Debug( `second input is empty "${ Z30000K2 }"` ); Wikifunctions.Error( 'Z30005', [ "Z30000K2", Z30000K2 ] ) } Wikifunctions.Debug( "both inputs are fine" ); return Z30000K1 + " " + Z30000K2; } </syntaxhighlight> Und das Gleiche in deiner Python3-Implementierung: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): if Z30000K1.strip() == "": Wikifunctions.Debug( 'first input is empty "'+Z30000K1+'"' ) Wikifunctions.Error("Z30005", ["Z30000K1", Z30000K1]) if Z30000K2.strip() == "": Wikifunctions.Debug( 'second input is empty "'+Z30000K2+'"' ) Wikifunctions.Error("Z30005", ["Z30000K2", Z30000K2]) Wikifunctions.Debug( 'both inputs are fine' ) return Z30000K1 + " " + Z30000K2 </syntaxhighlight> Auf diese Weise fügen wir deinen Debug-Protokollen in jedem Fall eine Meldung hinzu: * Schlägt der Funktionsaufruf bei der Überprüfung der ersten oder zweiten Eingabe fehl, ist das Ergebnis der Ausführung ein Fehler, enthält aber einen informativen Protokolleintrag darüber, welcher Zweig den Fehler verursacht hat. * Wenn der Funktionsaufruf erfolgreich ist — weil beide Eingaben gültig sind — gibt der Funktionsaufruf die verbundene Zeichenkette zurück, aber die zurückgegebenen Metadaten enthalten auch ein Debug-Protokoll. <span id="Debugging_your_compositions"></span> === Debuggen deiner Kompositionen === Zur Unterstützung des Debuggens von Kompositionen stellt Wikifunctions die integrierte Funktion {{Z|Z854}} bereit. Mit dieser Funktion kannst du Debug-Meldungen an die Ausführung jedes Funktionsaufrufs anhängen, der die endgültige Ausgabe erzeugt. Die während der Auswertung gesammelten Debug-Protokolle werden als Teil der Ausführungsmetadaten unter dem Schlüssel <code>executorDebugLogs</code> zurückgegeben. <span id="Add_debug_log_to_function_call_(Z854)"></span> ==== Debug-Protokoll zu Funktionsaufruf hinzufügen (Z854) ==== Die Funktion {{Z|Z854}} ist eine integrierte Funktion mit der ZID <code>Z854</code> und benötigt zwei Argumente: * '''Funktionsaufruf''' – Jede Komposition, die du ausführen möchtest. * '''Debug-Protokoll''' – Eine Zeichenketten-Meldung, die protokolliert wird, wenn der angegebene Funktionsaufruf ausgewertet wird. Wenn der umschlossene Funktionsaufruf ausgeführt wird, wird die bereitgestellte Meldung zu den Ausführungsprotokollen hinzugefügt. Wird dieser Funktionsaufruf nicht ausgeführt oder ist seine Ausführung nicht Teil der endgültigen Ausgabe, erscheint sein Debug-Protokoll nicht in den Metadaten des Endergebnisses. Diese integrierte Funktion ist besonders nützlich, wenn du beobachten möchtest: * Welcher Zweig einer Bedingung ausgeführt wurde, oder * Die Reihenfolge der Auswertung in einer Komposition. <span id="Using_Add_debug_log_to_function_call"></span> ==== Verwendung von Debug-Protokoll zu Funktionsaufruf hinzufügen ==== Angenommen, du möchtest zu unserer Beispielfunktion "verbinde zwei Zeichenketten mit Leerzeichen" oder <code>Z30000</code> Debug-Protokolle hinzufügen, sodass für die verschiedenen möglichen Ergebnisse unterschiedliche Meldungen angezeigt werden. Du könntest unsere integrierte Debugging-Funktion wie folgt verwenden: <syntaxhighlight lang="prolog"> if ( is_empty_string( Z30000K1 ), add_debug_log( throw_error( Z30005, ... ), 'failed on first input' ) if( is_empty_string( Z30000K2 ), add_debug_log( throw_error( Z30005, ... ), 'failed on second input' ), add_debug_log( join_with_separator( Z30000K1, Z30000K2, " " ), 'both inputs are ok!' ) ) ) </syntaxhighlight> Dies bewirkt Folgendes: * Wird die Funktion mit einer leeren ersten Eingabe aufgerufen, gibt sie eine Fehlermeldung zurück und die Metadaten enthalten einen Eintrag <code>executorDebugLogs</code> mit dem Protokoll-Eintrag "Fehler bei erster Eingabe". * Wird der Aufruf mit einer leeren zweiten Eingabe aufgerufen, schlägt der Aufruf ebenfalls fehl, die protokollierte Meldung lautet jedoch "Fehler bei zweiter Eingabe". * Bei Aufruf mit gültigen Eingaben gibt die Funktion eine erfolgreiche Antwort zurück und zusätzlich enthalten die Metadaten im Schlüssel <code>executorDebugLogs</code> "Beide Eingaben sind in Ordnung". So würde diese Komposition aussehen: [[File:Add debug log expanded.png|frame|center|alt=Implementierung der Komposition mit Debug-Protokoll hinzufügen, um alle möglichen Ausführungspfade zu protokollieren|Implementierung der Komposition mit Debug-Protokoll hinzufügen, um alle möglichen Ausführungspfade zu protokollieren]] <span id="Accessing_execution_debug_logs"></span> === Zugriff auf Ausführungs-Debug-Protokolle === Unabhängig davon, ob deine Ausführungsprotokolle über <code>Wikifunctions.Debug()</code> oder die integrierte Funktion {{Z|Z854}} hinzugefügt werden, werden sie als Teil der Antwort-Metadaten zurückgegeben. Um die Protokolle zu sehen, klicke nach dem Ausführen deiner Funktion auf die Schaltfläche "Details", die unten im Abschnitt "Ergebnis" erscheint. Die Fehler- und Debug-Informationen werden oben im Dialogfeld "Details" angezeigt. Dies ist das Ergebnis, das du sehen würdest, wenn du die Komposition aus unserem vorherigen Beispiel mit gültigen und ungültigen Eingaben ausführst: {| class="wikitable" | [[File:Execution logs success.png|frameless|center|alt=Funktions-Metadatendialog für eine erfolgreiche Ausführung mit Debug-Protokollen]] | [[File:Execution logs failure.png|frameless|center|alt=Funktions-Metadatendialog für eine fehlgeschlagene Ausführung mit Debug-Protokollen]] |- | Funktions-Metadatendialog für eine erfolgreiche Ausführung: zeigt keine Fehler an, sondern das Protokoll der erfolgreichen Ausführung: ''"Beide Eingaben sind in Ordnung!"'' | Funktions-Metadatendialog für eine fehlgeschlagene Ausführung: zeigt die Fehlerinformationen und das zusätzliche Ausführungsprotokoll für den ersten Fehlerzweig an: ''"Fehler bei erster Eingabe"'' |} [[Category:How to create implementations| {{#translation:}}]] n1ae0s8bb8d7cty8q14veahzsnqtxrj 333942 333940 2026-10-27T19:27:59Z Ameisenigel 44 Created page with "Die Fehlermeldung wird unter Verwendung der HTML-Meldung des Fehlertyps und der Werte der Fehlerargumente generiert." 333942 wikitext text/x-wiki <languages/> Diese Seite bietet eine detailliertere Anleitung dafür, wie man '''Implementierungen erstellt''' und geht über den Überblick auf {{ll|Wikifunctions:Introduction}} hinaus. <span id="Types_of_Implementations"></span> == Arten von Implementierungen == In Wikifunctions kann eine '''Implementierung''' zwei Hauptformen annehmen: '''Code''' oder '''Komposition'''. Eine Code-Implementierung drückt die Logik der Funktion direkt in einer der verfügbaren Programmiersprachen aus (derzeit Python3 oder JavaScript). Sie ist besonders nützlich, wenn sich das Verhalten der Funktion nicht ohne Weiteres aus bestehenden Wikifunktionen ableiten lässt oder wenn eine präzise Kontrolle über die Datenverarbeitung erforderlich ist. Eine Kompositions-Implementierung definiert die Funktion hingegen vollständig durch die Kombination bestehender Funktionen, ohne dass Code geschrieben werden muss. Kompositionen sind leichter verständlich, wiederverwendbar und lassen sich automatisch in andere Sprachen übersetzen. Sie setzen jedoch voraus, dass geeignete Bausteine ​​bereits vorhanden sind und sind oft weniger leistungsfähig. Prüfe daher zunächst, ob dein Ziel durch Komposition erreicht werden kann. Ist dies nicht möglich oder spielen Leistung oder feingranulare Logik eine Rolle, wähle stattdessen eine Code-Implementierung. Es gibt eine dritte Implementierungsart: '''integrierte Implementierungen'''. Diese werden vom Systemcode ausgeführt und können nicht bearbeitet werden. Höchstwahrscheinlich verfügen alle vordefinierten Funktionen über eine integrierte Implementierung. In solchen Fällen wird beim Öffnen der Implementierungsseite die Meldung ''"{{int|wikilambda-implementation-selector-none}}"'' angezeigt. <span id="Practice_Test-Driven_Development"></span> == Praxis der testgetriebenen Entwicklung == '''Testgetriebene Entwicklung''' oder '''TDD''' ist eine Methode zur Softwareentwicklung, bei der Tests geschrieben werden, bevor der eigentliche Code geschrieben wird. Tests dienen dazu, die Funktionsweise einer Funktion anhand von Beispielen und deren Funktionsweise zu verstehen. In Wikifunctions bietet das Schreiben von Tests als erste Tätigkeit erhebliche Vorteile. Wenn du an einer Implementierung arbeitest, kannst du deinen Code anhand der vorhandenen Tests ausführen, um sicherzustellen, dass er sich wie erwartet verhält. Dadurch lassen sich Fehler frühzeitig erkennen, noch bevor du deine Implementierung veröffentlichst. Tests sind außerdem ein effektives Mittel, um die benötigte Funktion zu beschreiben. Durch das Schreiben von Tests '''kommunizierst du klar das erwartete Verhalten''' und die Community kann bei der Implementierung helfen oder alternative Implementierungen erstellen. Stell dir vor, du möchtest eine Funktion implementieren, die zwei Zeichenketten mit einem Leerzeichen dazwischen verknüpft. Ein einfacher Test dafür könnte so aussehen: <syntaxhighlight lang="prolog"> join_with_space( "Hello", "world" ) => "Hello world" </syntaxhighlight> Sobald du das grundlegende Verhalten definiert hast, ist es wichtig, auch '''an Randfälle zu denken''' — Situationen, in denen die Eingaben so beschaffen sind, dass ein spezielles Verhalten erforderlich sein könnte. Was passiert beispielsweise, wenn deine erste Zeichenkette mit einem Leerzeichen endet oder deine zweite mit einem Leerzeichen beginnt? Soll die Funktion alle vorhandenen Leerzeichen beibehalten und ein weiteres hinzufügen oder ein sauber formatiertes Ergebnis mit nur einem Leerzeichen zwischen den Wörtern zurückgeben? Je nach deinen Anforderungen solltest du einen Test für einen solchen Fall erstellen. Ein Test für diesen Sonderfall könnte beispielsweise einer der folgenden sein — aber nicht beide!: <syntaxhighlight lang="prolog"> join_with_space( "Hello ", " world") => "Hello world" </syntaxhighlight> oder ... <syntaxhighlight lang="prolog"> join_with_space( "Hello ", " world") => "Hello world" </syntaxhighlight> Stell sicher, dass deine Tests alle möglichen Sonderfälle abdecken, und sobald du diese hast, stell sicher, dass sie alle mit der Funktion verbunden sind, indem du sie auswählst und auf "Verbinden" klickst. <span id="Code_implementations"></span> == Code-Implementierungen == [[File:Code implementation.png|thumb|alt=Wikifunctions-Code-Editor, der mit einer Funktionsvorlage initialisiert wurde|Beim Hinzufügen einer neuen Code-Implementierung wird die Funktionsvorlage mit den Funktions- und Argumentnamen initialisiert]] Beim Erstellen einer Implementierung mit Code richtet die Wikifunctions-Benutzeroberfläche einen Code-Editor ein, in dem die ausgewählte Sprache für Syntaxhervorhebung und -validierung aktiviert ist. Sobald die zu implementierende Funktion und die Programmiersprache ausgewählt sind, wird dieser Editor mit der korrekten Funktionsvorlage konfiguriert: '''Entferne oder bearbeite sie nicht!''' Platziere deinen Code innerhalb dieser Funktionssignatur. Falls du Hilfsfunktionen benötigst, kannst du diese einfach in deiner Hauptfunktionsdeklaration deklarieren. <span id="Using_input_types_in_your_code"></span> === Verwendung von Eingabetypen in deinem Code === Die Wikifunctions-Typen {{Z|Z6}} und {{Z|Z40}} können in JavaScript und Python3 wie native Typen verwendet werden. Beispielsweise lässt sich eine Zeichenkette verketten oder ein boolescher Wert direkt in einem logischen Ausdruck verwenden. Um andere Typen in deinen Code-Implementierungen zu verwenden, musst du den jeweiligen Typ genauer untersuchen, herausfinden, ob eine Umwandlung in ein natives Äquivalent existiert, und ihn entsprechend behandeln. Nehmen wir beispielsweise an, wir möchten Python-Code schreiben, der eine Eingabe vom Typ {{Z|Z20420}} verarbeitet. Auf der Seite für diesen Typ sehen wir uns die "Typumwandler in Code" an und suchen nach einem Python-Umwandler. Der Umwandler {{Z|Z20424}} wird auf unsere Datumseingabe angewendet, bevor unser Code ausgeführt wird. Unter "nativer Typ" sehen wir, dass unsere Eingabe ein Python-Dictionary ist, und in der Implementierung können wir die zu erwartenden Schlüssel sehen: <syntaxhighlight lang="python3"> return { 'K1': year, 'K2': month, 'K3': day } </syntaxhighlight> Wenn ein Typ keinen Umwandler besitzt, musst du direkt über seine Schlüssel auf seine Bestandteile zugreifen. Nehmen wir beispielsweise an, deine Funktion <code>Z30000</code> hat einen Eingabeparameter <code>Z30000K1</code> vom Typ {{Z|Z11}}. Dieser Typ besitzt zwei Schlüssel: <code>Z11K1</code> für die Sprache (selbst ein Objekt vom Typ {{Z|Z60}}) und <code>Z11K2</code> für den Zeichenketten-Wert. Das Sprachobjekt hat wiederum einen Schlüssel <code>Z60K1</code> für den Sprachcode. Um also eine Zeichenkette mit dem Sprachcode und dem Text zu erhalten, kannst du folgendes schreiben: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1 ) { // z. B. "de: beliebiger Text" return Z30000K1.Z11K1.Z60K1 + ": " + Z30000K1.Z11K2; } </syntaxhighlight> Für eine Kurzübersicht der verfügbaren Typumwandlungen besuche [[Special:MyLanguage/Wikifunctions:Execution targets#Default type conversion|die Tabelle der Standard-Typumwandlungen]]. <span id="Returning_the_right_outputs"></span> === Rückgabe der richtigen Ausgaben === Ähnlich wie bei der Behandlung von Eingaben müssen auch Ausgaben dem in der Funktionsdefinition angegebenen Typ entsprechen. Einige können wie native Typen behandelt werden; daher wird jede Zeichenketten-Ausgabe in ein Wikifunctions-Objekt {{Z|Z6}} und jeder von deiner Implementierung zurückgegebene native boolesche Wert in ein Wikifunctions-Objekt {{Z|Z40}} umgewandelt. Typen mit "Typumwandlern aus Code" wenden die entsprechende Funktion auf die Ausgabe an, um den benötigten Typ zu erzeugen. Am Beispiel von {{Z|Z20420}} transformiert {{Z|Z20443}} die Ausgabe deiner Implementierung – ein Dictionary mit den Schlüsseln K1, K2 und K3 – in die korrekte ZObjekt-Darstellung. Für Typen, die keine Umwandler aus Code haben, kannst du die Ausgabeobjekte sorgfältig erstellen und zurückgeben. Stell dir beispielsweise vor, unsere Funktion <code>Z30000</code> nimmt zwei Zeichenketten als Eingaben entgegen: Sprachcode und Text, und soll ein Objekt {{Z|Z11}} zurückgeben. In Python kannst du dies mit dem Konstruktor <code>ZObject</code> erreichen: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): lang_object = ZObject( {"Z1K1": "Z9", "Z9K1": "Z60"}, Z60K1 = Z30000K1 ) return ZObject( {"Z1K1": "Z9", "Z9K1": "Z11"}, Z11K1 = lang_object, Z11K2 = Z30000K2 ) </syntaxhighlight> Oder in JavaScript: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1, Z30000K2 ) { const langObject = new ZObject( new Map( [ [ "Z60K1", Z30000K1 ] ] ), { "Z1K1": "Z9", "Z9K1": "Z60" } ); const monolingualKeys = new Map( [ [ "Z11K1", langObject ], [ "Z11K2", Z30000K2 ] ] ); return new ZObject( monolingualKeys, { "Z1K1": "Z9", "Z9K1": "Z11" } ); } </syntaxhighlight> Du kannst mehr über die Klasse <code>ZObject</code> und andere nützliche Konstruktoren auf {{ll|Wikifunctions:Execution_targets#Custom_and_non-built-in_type_conversion}} erfahren. {{phab|T392750}}Stand Mai 2026 kann der Versuch, eine Liste von Listen zurückzugeben, fehlschlagen; daher ist es nicht möglich, solche Funktionen in Code zu implementieren. === Code in Python === In diesem Abschnitt geben wir ein konkretes Beispiel, wie man eine Implementierung in Form von Code in Python erstellt. Angenommen, wir möchten eine Implementierung für eine Funktion erstellen, die zwei Eingabezeichenketten durch Einfügen eines Leerzeichens dazwischen kombiniert und das Ergebnis zurückgibt. Nehmen wir an, die ZID dieser Funktion ist Z30000. Die Implementierung wird über die ZID der Funktion definiert. Das gilt auch für die Argumente der Funktion. Im Fall der Funktion Z30000 mit ihren beiden Argumenten sollte die Funktionsvorlage also so aussehen: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): </syntaxhighlight> Wie bereits erwähnt, wissen wir, dass die Argumente (<code>Z30000K1</code> und <code>Z30000K2</code>) Zeichenketten sind, daher können wir sie genauso behandeln wie native Zeichenketten in Python. Die Funktion sollte außerdem eine Zeichenkette zurückgeben. In unserem Beispiel geben wir einfach die beiden Argumente, getrennt durch ein Leerzeichen, aneinandergereiht zurück: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): return Z30000K1 + " " + Z30000K2 </syntaxhighlight> Da es sich um Python handelt, vergesse nicht, diese Zeile einzurücken. Wenn du unserem Rat gefolgt bist, [[#Practice Test-Driven Development|TDD anzuwenden]], verfügst du bereits über eine Reihe von Tests, von denen du weißt, dass sie funktionieren sollten. In diesem Fall kannst du während der Entwicklung deiner Implementierung auf den kreisförmigen Pfeil im Testbereich klicken und überprüfen, ob deine Implementierung alle Tests besteht. Denke daran, dass die Laufzeit keinen Status hat. Gehe nicht von Werten für globale oder statische Variablen aus. Wenn du weitere Fragen dazu hast, was du in Python tun kannst und was nicht, frage auf [[Wikifunctions:Python implementations]]. === Code in JavaScript === In diesem Abschnitt geben wir ein konkretes Beispiel, wie man eine Implementierung in Form von Code in JavaScript erstellt. Angenommen, wir möchten eine Implementierung für eine Funktion erstellen, die zwei Eingabezeichenketten durch Einfügen eines Leerzeichens dazwischen kombiniert und das Ergebnis zurückgibt. Nehmen wir an, die ZID dieser Funktion ist <code>Z30000</code>. Die Implementierung wird über die ZID der Funktion definiert. Das gilt auch für die Argumente der Funktion. Im Fall der Funktion <code>Z30000</code> mit ihren beiden Argumenten sollte die Funktionsvorlage also so aussehen: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1, Z30000K2 ) { } </syntaxhighlight> Wir wissen, dass die Argumente (<code>Z30000K1</code> und <code>Z30000K2</code>) Zeichenketten sind, daher können wir sie in JavaScript wie native Zeichenketten behandeln. Die Funktion soll außerdem eine Zeichenkette zurückgeben. Um die Funktion zu vervollständigen, kannst du eine Zeile hinzufügen, die die Eingabezeichenketten verkettet, etwa so: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1, Z30000K2 ) { return Z30000K1 + " " + Z30000K2; } </syntaxhighlight> Wenn du Tests wie im Abschnitt [[#Practice Test-Driven Development|TDD]] oben empfohlen hast, klicke auf den kreisförmigen Pfeil im Testbereich und prüfe, ob deine Implementierung alle Tests besteht. Denke daran, dass die Laufzeit keinen Status hat. Gehe nicht von Werten für globale oder statische Variablen aus. Wenn du weitere Fragen dazu hast, was du in JavaScript tun kannst und was nicht, frage auf [[Wikifunctions:JavaScript implementations]]. <span id="Calling_another_Wikifunctions_function"></span> === Aufruf einer anderen Wikifunctions-Funktion === Eine Code-Implementierung kann bestimmte andere Wikifunctions-Funktionen aufrufen, die Ausgabe des Aufrufs empfangen und diese Ausgabe für die weitere Verarbeitung nutzen. Wir bezeichnen solche Aufrufe als Callbacks. Derzeit können aus Sicherheits- und Leistungsgründen nur die folgenden integrierten Wikidata-Abruf- und Suchfunktionen auf diese Weise aufgerufen werden: {{Z|Z6820}}, {{Z|Z6821}}, {{Z|Z6822}}, {{Z|Z6824}}, {{Z|Z6825}}, {{Z|Z6826}}, {{Z|Z6830}} und {{Z|Z6831}}. Diese Funktionalität befindet sich in einem frühen Stadium der Einführung; wir hoffen, in Zukunft Aufrufe für eine größere Bandbreite an Funktionen zu ermöglichen. Betrachten wir eine JavaScript-Implementierung, die einen Callback enthält. Diese Implementierung ruft ein Datenobjekt von Wikidata ab, extrahiert die Bezeichnung dieses Datenobjektes in einer bestimmten Sprache und gibt die Bezeichnung als Zeichenkette zurück. Das abzurufende Datenobjekt wird über das Argument <code>Z400K1</code> angegeben, die Sprache über <code>Z400K2</code>. <syntaxhighlight lang="javascript"> function Z400( Z400K1, Z400K2 ) { const item = Wikifunctions.Call('Z6821', Z400K1); for (const label of item.Z6001K2.Z12K1) { if (label.Z11K1.Z60K1 === Z400K2.Z60K1) { return label.Z11K2; }} return 'NOT FOUND'; } </syntaxhighlight> Ein Callback wird durch den Aufruf von <code>Wikifunctions.Call</code> ausgelöst, wie im Beispiel gezeigt. Das erste Argument für <code>Wikifunctions.Call</code> ist stets die ZID der aufzurufenden Funktion – in diesem Fall {{Z|Z6821}}, welche ein einzelnes Argument entgegennimmt. Darauf folgen, durch Kommas getrennt, die an diese Funktion zu übergebenden Argumente. Hierbei handelt es sich bei dem Argument <code>Z400K1</code> um denselben Wert, der auch an <code>Z400</code> übergeben wurde. Dies ist ein gängiges Muster für die Argumentübergabe an Callbacks, jedoch können die Argumente auch mit dem Konstruktor <code>ZObject</code> (wie oben beschrieben) erstellt oder auf andere Weise bezogen werden. Der Wert von <code>Z400K1</code> wäre eine Instanz von {{Z|Z6091}}, die die QID des abzurufenden Datenobjekts enthält. Zeile 2 des Beispiels ruft <code>Z6821</code> auf, um dieses Datenobjekt von Wikidata abzurufen, und weist das resultierende ZObjekt der Konstante <code>item</code> zu. Der restliche Code durchläuft die Bezeichnungen des Datenobjekts, bis er diejenige findet, die der durch <code>Z400K2</code> angegebenen Sprache entspricht. Für das obige Beispiel haben wir der Einfachheit halber <code>Z6821</code> verwendet. Sofern die Implementierung jedoch nicht das gesamte Objekt benötigt, wird dringend empfohlen, zum Abrufen von Wikidata-Datenobjekten, die sehr groß sein können, <code>Z6820</code> zu verwenden. Obwohl der Aufruf von <code>Z6820</code> etwas komplexer ist, ermöglichen seine Parameter das Abrufen spezifischer Teile eines Wikidata-Datenobjekts. Dies kann die Leistung erheblich steigern und bestimmte Fehler vermeiden, da weniger Netzwerkbandbreite und Verarbeitungszeit erforderlich sind. (<code>Z6820</code> kann auch statt <code>Z6822</code>, <code>Z6824</code>, <code>Z6825</code> und <code>Z6826</code> verwendet werden, um ähnliche Vorteile bei der Bandweitenreduzierung zu erreichen.) Im Folgenden zeigen wir, wie <code>Z6820</code> in <code>Wikifunctions.Call</code> verwendet werden kann, um dasselbe Verhalten wie oben zu erzielen. Beachte, dass wir das zweite an <code>Z6820</code> übergebene Argument, <code>[labelsPart]</code>, nutzen, um festzulegen: “Gib nur die Bezeichnungen des Datenobjekts zurück”, und das dritte Argument, <code>[Z400K2]</code>, verwenden, um festzulegen: “Gib die Bezeichnungen nur in der angegebenen Sprache zurück”. (Dieses Argument würde auch für Aliasse und Beschreibungen gelten, sofern diese im Ergebnis enthalten wären.) <syntaxhighlight lang="javascript"> function Z400( Z400K1, Z400K2 ) { const labelsPart = new ZObject( new Map( [ ['Z6030K1', new ZReference('Z6033')] ] ), {Z1K1: 'Z9', Z9K1: 'Z6030'} ); const entities = Wikifunctions.Call( 'Z6820', [Z400K1], [labelsPart], [Z400K2], []); const item = entities.get(Z400K1.Z6091K1); const labels = item.Z6001K2.Z12K1; for (const label of labels) { if (label.Z11K1.Z60K1 === Z400K2.Z60K1) { return label.Z11K2; }} return 'NOT FOUND'; } </syntaxhighlight> Weitere zu beachtende Hinweise: * Obwohl Code-Implementierungen mittlerweile in der Lage sind, Wikidata-Entitäten abzurufen, wird empfohlen, dass sie keine ''vollständigen'' Entitäten zurückgeben. Dies liegt an den derzeitigen Beschränkungen hinsichtlich der Größe des von einer Code-Implementierung zurückgegebenen Wertes. Um eine vollständige, große Entität abzurufen und zurückzugeben, ist es besser, die Abruffunktion aus einer Komposition heraus aufzurufen. * Es kann nur ein Callback gleichzeitig ausgeführt werden. Aus Sicherheitsgründen ist es nicht möglich, die Nebenläufigkeitsfunktionen von JavaScript oder Python zu nutzen, um mehrere Callbacks parallel auszuführen. ** Beachte jedoch, dass du mithilfe von Z6820 mehrere Entitäten auf einmal abrufen kannst. * Derzeit gibt es eine Obergrenze von 3 MiB für die Größe von Wikidata-Inhalten, die über einen einzelnen Callback an eine Code-Implementierung zurückgegeben werden können. Dieselbe Obergrenze gilt für die Größe des Ergebnisses, das von einer Code-Implementierung zurückgegeben wird. <span id="Compositions"></span> == Kompositionen == Im diesem Abschnitt geben wir ein konkretes Beispiel, wie man eine Implementierung in Form einer Komposition erstellt. Angenommen, wir möchten eine Implementierung für eine Funktion erstellen, die zwei Eingabezeichenketten durch Einfügen eines Leerzeichens dazwischen kombiniert und das Ergebnis zurückgibt. Nehmen wir an, die ZID dieser Funktion ist <code>Z30000</code>. Normalerweise ist es sinnvoll, zunächst darüber nachzudenken, wie man vorhandene Funktionen kombinieren kann, um die gewünschte Ausgabe zu erzielen. Manchmal mag dies trivial sein und du kannst einfach mit dem Zusammenstellen und Funktionen fortfahren, aber in vielen Fällen lohnt es sich, die gewünschte Komposition zu notieren. Beispielsweise könnten wir für die angegebene Funktion die vorhandene Funktion {{Z|Z10000}} verwenden. Diese Funktion nimmt zwei Zeichenketten und erstellt daraus eine Zeichenkette. Aber wir müssen dazwischen ein Leerzeichen einfügen. Wir verbinden also zunächst ein Leerzeichen mit dem Ende der ersten Zeichenkette und verbinden dann die zweite Zeichenfolge mit dem Ergebnis dieser ersten Verbindung. Unsere Komposition könnte also so notiert werden: <syntaxhighlight lang="prolog"> join_strings( join_strings( Z30000K1, " " ), Z30000K2 ) </syntaxhighlight> Es gibt mehrere Möglichkeiten, eine Komposition zu schreiben: Beachte, dass dasselbe auch auf folgende Weise erreicht werden kann: <syntaxhighlight lang="prolog"> join_strings( Z30000K1, join_strings( " ", Z30000K2 ) ) </syntaxhighlight> Eine alternative Implementierung könnte auch die vorhandene Funktion {{Z|Z15175}} verwenden, sodass deine Komposition wie folgt aussehen könnte: <syntaxhighlight lang="prolog"> join_with_separator( Z30000K1, Z30000K2, " " ) </syntaxhighlight> Wie du siehst, gibt es mehrere Möglichkeiten, dies zu erreichen. Nimm dir also Zeit und erkunde die vorhandenen Funktionen, die im {{ll|Wikifunctions:Catalogue}} verfügbar sind. Versuchen wir, das zweite Beispiel zu erstellen, <code>join_strings(Z30000K1, join_strings(" ", Z30000K2))</code>. Um dies zu erstellen: # Um eine Implementierung hinzuzufügen, klicke auf der Funktionsseite in der Tabelle "Implementierungen" auf die Schaltfläche "+". # Stelle sicher, dass die Option "Komposition" unter "Implementierung" ausgewählt ist. # Klicke auf das Symbol "›" oder auf den Link "Funktion auswählen", um die Funktionsdetails anzuzeigen. # Suche unter "Funktion" nach dem Namen der äußersten Funktion, die du verwenden möchtest, in diesem Beispiel "verbinde Zeichenketten". Wähle anschließend die gewünschte Funktion aus der Dropdown-Liste aus. # Du siehst zwei neue Felder, eines für jedes der Argumente, die für die ausgewählte Funktion benötigt werden. # Als erstes Argument möchten wir den ersten Eingabewert für unsere Funktion auswählen: ## Klicke neben "erste Zeichenkette" auf die Schaltfläche "…" und wähle "Argumentreferenz" aus. ## Unter "Schlüssel-ID" kannst du nun die erste Zeichenkette deiner Funktion aus dem Dropdown-Menü auswählen, das alle verfügbaren Eingaben enthält. # Für das zweite Argument möchten wir das Ergebnis eines weiteren Aufrufs von "verbinde Zeichenketten" verwenden: ## Klicke neben "zweite Zeichenkette" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus. ## Suche unter "Funktion" nach der Funktion, die du aufrufen möchtest und wähle sie aus, nämlich "verbinde Zeichenketten". ## Konfiguriere die "erste Zeichenkette" für diesen inneren Funktionsaufruf, indem du einfach ein Leerzeichen in das Textfeld eingibst, und konfiguriere die "zweite Zeichenkette" wie in Schritt 6: Ändere sie mit der Schaltfläche "…" in "Argumentreferenz" und wähle dann das zweite Argument in der Dropdown-Liste aus. Deine Komposition ist nun fertig! Du kannst die Details mithilfe der Pfeiltasten ein- und ausblenden, um dir einen Überblick zu verschaffen. Falls du bereits Tests wie im Abschnitt [[#Practice Test-Driven Development|TDD]] oben empfohlen implementiert hast, klicke im Testbereich auf den kreisförmigen Pfeil und prüfe, ob deine Implementierung die Tests besteht. Sobald deine Komposition die Tests bestanden hat, kannst du sie veröffentlichen. [[File:Composition implementation expanded.png|frame|center|alt=Eine Wikifunctions-Kompositionsimplementierung in ihrer erweiterten Ansicht|Eine Wikifunctions-Kompositionsimplementierung in ihrer erweiterten Ansicht]] [[File:Composition implementation collapsed.png|frame|center|alt=Eine Wikifunctions-Kompositionsimplementierung in ihrer reduzierten Ansicht|Eine Wikifunctions-Kompositionsimplementierung in ihrer reduzierten Ansicht]] <span id="Wikifunctions_error_handling"></span> == Fehlerbehandlung auf Wikifunctions == Als Ersteller einer Wikifunctions-Funktion möchtest du möglicherweise den Benutzer warnen, der deine Funktion aufruft, wenn im Code ein Fehler auftritt oder seine Eingaben bestimmte Kriterien nicht erfüllen. Wenn deine Funktion beispielsweise eine Zeichenkette mit einem Namen erwartet, solltest du prüfen, ob der Name nicht leer ist, und gegebenenfalls eine verständliche Fehlermeldung anzeigen. Hierfür kannst du <code>Wikifunctions.Error()</code> in deinen Code-Implementierungen oder die Funktion {{Z|Z851}} in deinen Kompositionen verwenden. In diesem Abschnitt erfährst du: * Wie man Fehler sowohl aus Code- als auch aus Kompositions-Implementierungen auslöst, * wie man Tests für Fehlerfälle schreibt, und * wie man Fehler abfängt und behandelt, die von Funktionen ausgelöst werden, die man in seinen Kompositionen verwendet. <span id="Throwing_errors_from_code_implementations"></span> === Fehler aus Code-Implementierungen auslösen === Sowohl beim Schreiben von JavaScript- als auch von Python-Code kannst du <code>Wikifunctions.Error()</code> nutzen, um die Ausführung mit einem gewünschten Fehler zu beenden. <code>Wikifunctions.Error()</code> hat zwei Parameter: # Fehlertyp: Eine Zeichenkette, die die ZID des Fehlertyps enthält, den du zurückgeben möchtest. # Fehlerargumente: Eine Liste von Zeichenkettenargumenten zur Erstellung des Fehlers. Gehen wir sie der Reihe nach durch: <span id="Error_type"></span> ==== Fehlertyp ==== Ein Fehlertyp ist ein Objekt, das eine Art von Fehler beschreibt, der im System auftreten kann. Es gibt eine Reihe vordefinierter Fehlertypen, du kannst aber auch eigene Fehlertypen erstellen, die besser zu deinem Anwendungsfall passen. Bei der Verwendung von Fehlern empfiehlt es sich, die verfügbaren Fehlertypen zu durchsuchen, die sich in [[Special:ListObjectsByType/Z50|dieser Liste]] finden. Falls keine passenden Fehler für deinen Fall vorhanden sind, erstelle einen neuen Fehler, indem du zur Erstellungsseite gehst und im Typauswahlfeld "Fehlertyp" auswählst. Lege anschließend die erforderlichen Felder fest: [[File:Error type.png|thumb|alt=Erstellung von Fehlertypen in Wikifunctions|Um einen neuen Fehlertyp (Z50) zu erstellen, bearbeite die Bezeichnung und füge die erforderlichen Schlüssel hinzu.]] * '''Bezeichnung''' – Dies ist der Haupttitel des Fehlers, der eine kurze, aber aussagekräftige Meldung enthalten sollte. Lege die Fehlerbezeichnung im rechten Feld mit dem Titel "Info" fest. * '''Schlüssel''' – Schlüssel enthalten zusätzliche Informationen zur Fehlerursache. Wenn beispielsweise eine Eingabe das falsche Format aufwies, möchtest du den Benutzer möglicherweise über den eingegebenen Inhalt informieren, wenn der Fehler auftritt. Um sie in deinen Implementierungen zu verwenden, müssen Schlüssel vom Zeichenketten sein. Um einen Schlüssel zu erstellen, klicke auf das Symbol "[+]" unterhalb von "Schlüssel", wähle unter "Werttyp" die Option "Zeichenkette" aus und füge eine aussagekräftige Bezeichnung hinzu, beispielsweise "tatsächlich Eingabe". Sobald du alle erforderlichen Schlüssel erstellt hast, kannst du deinen Fehlertyp veröffentlichen und die ID des neu erstellten Objekts speichern. * '''Fehlermeldung''' – Fehlertypen können ein mehrsprachiges Array von Fehlermeldungen enthalten, die mit HTML-Parametern versehen sind. Die Parameter werden als $1, $2 etc. angegeben, wobei die Ziffer dem Schlüssel des Fehlertyps entspricht. Beim Erstellen eines Fehlertyps mit dem Zeichenketten-Schlüssel "aktuelle Eingabe", kann die Fehlermeldung beispielsweise den Platzhalter "$1" verwenden, der zum Zeitpunkt der Fehlerausgabe durch den Wert des Schlüssels "aktuelle Eingabe" ersetzt wird. Um HTML-Meldungen hinzuzufügen, klicke unter "HTML-Fragmente" auf das Symbol "[+]", wähle eine Sprache aus und gib die HTML-Zeichenkette ein. <span id="Error_arguments"></span> ==== Fehlerargumente ==== Fehlerargumente entsprechen den Schlüsseln des Fehlertyps und sollten zusätzliche Informationen zum Verständnis des Fehlers liefern. Fehlerargumente sollten immer Zeichenketten sein. <span id="Using_Wikifunctions.Error()"></span> ==== Verwendung von Wikifunctions.Error() ==== Angenommen, du möchtest einen Fehler auslösen, wenn entweder deine erste oder deine zweite Eingabe leer ist. Du hast den Fehlertyp bereits erstellt und ihm wurde die ZID <code>Z30005</code> zugewiesen. Dein Fehlertyp hat zwei Zeichenketten-Schlüssel: * Eingabeschlüssel: Enthält den Schlüssel der fehlerhaften Eingabe * Eingabewert: Enthält den aktuellen Wert der fehlerhaften Eingabe Um einen Fehler in deiner JavaScript-Implementierung auszulösen, solltest du etwa Folgendes tun: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1, Z30000K2 ) { if ( trim( Z30000K1 ) === '' ) { // Wenn die erste Eingabe leer ist, löse Fehler Z30005 aus // mit zwei Zeichenketten-Argumenten: [ erster Eingabe-Schlüssel, erster Eingabe-Wert ] Wikifunctions.Error( 'Z30005', [ "Z30000K1", Z30000K1 ] ) } if ( trim( Z30000K2 ) === '' ) { // Wenn die zweite Eingabe leer ist, löse Fehler Z30005 aus // mit zwei Zeichenketten-Argumenten: [ zweiter Eingabe-Schlüssel, zweiter Eingabe-Wert ] Wikifunctions.Error( 'Z30005', [ "Z30000K2", Z30000K2 ] ) } return Z30000K1 + " " + Z30000K2; } </syntaxhighlight> Um einen Fehler in deiner Python-Implementierung auszulösen, solltest du etwa Folgendes tun: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): if Z30000K1.strip() == "": # Wenn die erste Eingabe leer ist, löse Fehler Z30005 aus # mit zwei Zeichenketten-Argumenten: [ erster Eingabe-Schlüssel, erster Eingabe-Wert ] Wikifunctions.Error("Z30005", ["Z30000K1", Z30000K1]) if Z30000K2.strip() == "": # Wenn die zweite Eingabe leer ist, löse Fehler Z30005 aus # mit zwei Zeichenketten-Argumenten: [ erster Eingabe-Schlüssel, erster Eingabe-Wert ] Wikifunctions.Error("Z30005", ["Z30000K2", Z30000K2]) return Z30000K1 + " " + Z30000K2 </syntaxhighlight> Denke daran, dass der Aufruf von <code>Wikifunctions.Error()</code> die Ausführung beendet! <span id="Throwing_errors_from_compositions"></span> === Fehler aus Kompositionen auslösen === Wenn du eine Kompositionsimplementierung erstellst, kannst du einen Fehler auslösen, indem du die Spezialfunktion {{Z|Z851}} aufrufst. <span id="Throw_Error_function_(Z851)"></span> ==== Funktion Fehler auslösen (Z851) ==== Die Funktion {{Z|Z851}} ähnelt der Methode <code>Wikifunctions.Error()</code> und benötigt zwei Argumente: * '''Fehlertyp''' – Ein Verweis auf den Fehlertyp, den du auslösen möchtest * '''Fehlerparameter''' – Eine Liste mit den Argumenten zur Erstellung deines Fehlers, die ebenfalls Zeichenketten sein sollten. <span id="Using_Throw_Error"></span> ==== Verwendung von Fehler auslösen ==== Angenommen, du möchtest deine Komposition so ändern, dass sie zuerst prüft, ob die Argumente nicht leer sind, und einen Fehler ausgibt, wenn sie ein leeres Argument findet. Wenn dann keines der Argumente leer ist, wird die ursprüngliche Komposition ausgeführt, die wie folgt aussieht: <syntaxhighlight lang="prolog"> join_with_separator( Z30000K1, Z30000K2, " " ) </syntaxhighlight> Dazu musst du bedingte Pfade erstellen, für die du die Funktion {{Z|Z802}} verwenden kannst. Stell es dir folgendermaßen vor: * Wenn das erste Argument leer ist, soll ein Fehler für das erste Argument ausgelöst werden * Andernfalls wird mit der Überprüfung des zweiten Arguments fortgefahren * Wenn das zweite Argument leer ist, soll ein Fehler für das zweite Argument ausgelöst werden * Andernfalls wird der Erfolgspfad verfolgt und die verbundenen Zeichenketten mit dem Leerzeichen als Trennzeichen zurückgegeben Oder in funktionalem Pseudocode: <syntaxhighlight lang="prolog"> if ( is_empty_string( Z30000K1 ), throw_error( Z30005, [ "Z30000K1", Z30000K1 ] ), if( is_empty_string( Z30000K2 ), throw_error( Z30005, [ "Z30000K2", Z30000K2 ] ), join_with_separator( Z30000K1, Z30000K2, " " ) ) ) </syntaxhighlight> Lass uns das Schritt für Schritt erstellen: # Um eine Implementierung hinzuzufügen, klicke auf der Funktionsseite in der Tabelle "Implementierungen" auf die Schaltfläche "+". # Stelle sicher, dass die Option "Komposition" unter "Implementierung" ausgewählt ist. # Klicke auf das Symbol "›" oder auf den Link "Funktion auswählen", um die Funktionsdetails anzuzeigen. # Suche unter "Funktion" nach der äußersten Funktion, die du verwenden möchtest, in diesem Fall "wenn", und wähle sie aus. # Überprüfe die Gültigkeit des ersten Arguments: ## Klicke neben "Bedingung" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "ist leere Zeichenkette" und wähle sie aus ## Klicke neben "Eingabe" auf die Schaltfläche "…" und wähle "Argumentreferenz" aus ## Wähle unter "Schlüssel-ID" die erste Eingabe aus (z. B. "erste Zeichenkette") ## Du kannst den Funktionsaufruf der "Bedingung" nun bei Bedarf ausblenden, indem du auf den Pfeil nach unten neben "Bedingung" klickst. Es sollte dann etwa Folgendes angezeigt werden: "f(x) ist leere Zeichenkette ( → erste Zeichenkette )" # Fehler auslösen, wenn die Bedingung wahr ist: ## Klicke neben "dann" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "Fehler auslösen" und wähle sie aus ## Suche unter "Fehlertyp" nach deinem Fehlertyp (du kannst die Fehler-ID direkt eingeben, wenn du sie kennst, z. B. Z30005) und wähle ihn aus ## Füge unter "Fehlerparameter" zwei Elemente hinzu, indem du auf die Schaltfläche "+" klickst ## Lege für "Objekt 1" (fehlerhafter Argumentschlüssel) den Typ auf "Zeichenkette" fest und trage die Argumentkennung ein (z. B. "erste Eingabe" oder "Z30000K1") ## Klicke für "Objekt 2" (fehlerhafter Argumentwert) auf die "…" neben "Objekt 2" und wähle "Argumentreferenz" aus ## Wähle unter "Schlüssel-ID" die erste Eingabe aus (z. B. "erste Zeichenkette") ## Du kannst den Funktionsaufruf "dann" nun bei Bedarf ausblenden, indem du auf den Pfeil nach unten neben "dann" klickst. Es sollte dann etwa Folgendes angezeigt werden: "f(x) Fehler auslösen ( ungültiges Format, typisierte Liste ( Objekt, "erste Eingabe", → erste Zeichenkette ) )" # Prüfe das zweite Argument, wenn das erste korrekt war: ## Klicke neben "sonst" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "wenn" und wähle sie aus ## Richte eine "Bedingung" ein, um die Gültigkeit des zweiten Arguments zu überprüfen, indem du das gleiche Verfahren wie in Schritt 5 beschrieben anwendest. ## Richte "dann" so ein, dass beim zweiten Argument ein Fehler ausgelöst wird, indem du das gleiche Verfahren wie in Schritt 6 beschrieben anwendest. # Richte schließlich den Erfolgspfad ein: ## Klicke neben dem verschachtelten "sonst" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der gewünschten Funktion, in diesem Fall "vereinige zwei Zeichenketten mit Trennzeichen", und wähle sie aus ## Klicke neben "erste Zeichenkette" auf die Schaltfläche "…" und setze sie auf "Argumentreferenz", wähle anschließend "erste Zeichenkette" aus ## Klicke neben "zweite Zeichenkette" auf die Schaltfläche "…" und setze sie auf "Argumentreferenz", wähle anschließend "zweite Zeichenkette" aus ## Füge unter "Trennzeichen" ein Leerzeichen in das Textfeld ein Der resultierende Funktionsaufruf sollte folgendermaßen aussehen: [[File:Throw error expanded.png|frame|center|alt=Wikifunctions-Komposition mit der Funktion Fehler auslösen|Wikifunctions-Komposition mit der Funktion Fehler auslösen]] [[File:Throw error collapsed.png|frame|center|alt=Wikifunctions-Komposition mit der Funktion Fehler auslösen in ihrer reduzierten Ansicht|Wikifunctions-Komposition mit der Funktion Fehler auslösen in ihrer reduzierten Ansicht]] <span id="Handling_errors_in_compositions"></span> === Fehlerbehandlung in Kompositionen === Es ist zwar nützlich, Funktionen das Auslösen erwarteter Fehler zu ermöglichen, aber es ist entscheidend, Fehler in den eigenen Kompositionen behandeln zu können, um diese Funktionen sicher verwenden zu können. Angenommen, du möchtest eine neue Funktion "vollständiger Name einer Person" erstellen – wir bezeichnen sie mit der ZID <code>Z30010</code>. Diese Funktion soll den vollständigen Namen einer Person anhand ihres Vor- und Nachnamens zurückgeben. Ist jedoch eines der beiden Felder leer, soll sie stattdessen den Text "Unbekannt" zurückgeben. Du könntest eine Komposition erstellen, indem du unsere Beispielfunktion "verbinde zwei Zeichenketten mit Leerzeichen" oder <code>Z30000</code> verwendest, um den Namen zu generieren. Wenn eine der Eingaben leer ist, weißt du, dass <code>Z30000</code> einen Fehler vom Typ <code>Z30005</code> auslöst. Mithilfe der Funktion {{Z|Z850}} als Wrapper kannst du die Verbindungsoperation ausführen und einen möglichen Fehler abfangen, indem du einfach "Unbekannt" zurückgibst, wenn er auftritt. <span id="Try-Catch_function_(Z850)"></span> ==== Try-Catch-Funktion (Z850) ==== Die Funktion {{Z|Z850}} ist eine integrierte Funktion mit der ZID <code>Z850</code> und benötigt drei Argumente: * '''Funktionsaufruf''' – Der erste Funktionsaufruf, der ausgeführt werden soll. Wenn kein Fehler auftritt, ist die Antwort das Ergebnis dieses Funktionsaufrufs. * '''Fehlertyp''' – Ein Fehlertyp, der abgefangen werden soll, falls er während der Ausführung des ersten Funktionsaufrufs auftritt. * '''Fehlerhandler''' – Ein Funktionsaufruf, der ausgeführt wird, falls der oben genannte Fehler während der Ausführung des ursprünglichen Funktionsaufrufs auftritt. In diesem Fall wird das Ergebnis der Fehlerbehandlung zurückgegeben. <span id="Using_Try-Catch"></span> ==== Verwendung der Try-Catch-Funktion ==== Sobald wir alle Funktionen für unsere Komposition haben, können wir sie folgendermaßen gestalten: <syntaxhighlight lang="prolog"> try_catch( join_with_space( Z30010K1, Z30010K2 ), Z30005, echo( "Unknown" ) ) </syntaxhighlight> Das bedeutet: * Die Funktion "verbinde zwei Zeichenketten mit Leerzeichen" wird mit den beiden Eingaben ausprobiert und wenn alles erfolgreich verläuft, wird das Ergebnis dieser Funktion zurückgegeben * Wenn eine der Eingaben leer ist, löst "verbinde zwei Zeichenketten mit Leerzeichen" einen Fehler vom Typ <code>Z30005</code> aus * Unsere {{Z|Z850}} erkennt dann diesen Fehler und führt die Funktion {{Z|Z801}} aus, die "Unbekannt" zurückgibt Lass uns das Schritt für Schritt erstellen: # Um eine Implementierung hinzuzufügen, klicke auf der Funktionsseite in der Tabelle "Implementierungen" auf die Schaltfläche "+". # Stelle sicher, dass die Option "Komposition" unter "Implementierung" ausgewählt ist. # Klicke auf das Symbol "›" oder auf den Link "Funktion auswählen", um die Funktionsdetails anzuzeigen. # Suche unter "Funktion" nach der äußersten Funktion, die du verwenden möchtest, in diesem Fall "Try-Catch-Funktion", und wähle sie aus. # Richte den Hauptfunktionsaufruf ein: ## Klicke unterhalb des Feldes, in dem die "Try-Catch-Funktion" ausgewählt ist, neben dem Schlüssel "Funktionsaufruf" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "verbinde zwei Zeichenketten mit Leerzeichen" und wähle sie aus ## Klicke neben "erste Zeichenkette" auf die Schaltfläche "…" und wähle "Argumentreferenz" aus, wähle anschließend das Argument "erster Name" aus der Dropdown-Liste aus. ## Klicke neben "zweite Zeichenkette" auf die Schaltfläche "…" und wähle "Argumentreferenz" aus, wähle anschließend das Argument "zweiter Name" aus der Dropdown-Liste aus. # Wähle den abzufangenden Fehler aus: ## Suche unter "Fehlertyp" nach "ungültige Zeichenkette" und wähle es aus – du kannst direkt nach der ZID <code>Z30005</code> suchen # Richte den Funktionsaufruf für den Fehlerhandler ein: ## Klicke neben "Fehlerhandler" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "Echo" und wähle sie aus ## Suche unter "Eingabe" und "Typ" den Typ "Zeichenkette" und wähle ihn aus ## Gib nun unter "Eingabe" im Textfeld "Unbekannt" ein Die resultierende Funktion sollte folgendermaßen aussehen: [[File:Try catch expanded.png|frame|center|alt=Wikifunctions-Komposition mit der Try-Catch-Funktion in ihrer erweiterten Ansicht|Wikifunctions-Komposition mit der Try-Catch-Funktion in ihrer erweiterten Ansicht]] [[File:Try catch collapsed.png|frame|center|alt=Wikifunctions-Komposition mit der Try-Catch-Funktion in ihrer reduzierten Ansicht|Wikifunctions-Komposition mit der Try-Catch-Funktion in ihrer reduzierten Ansicht]] <span id="Testing_your_failure_use_cases"></span> === Testen deiner Fehlerfälle === Wie bereits im Abschnitt über die [[#Practice Test-Driven Development|Anwendung von TDD]] erläutert, ist es wichtig, nicht nur die häufigsten Ausführungspfade, sondern auch mögliche Randfälle zu testen. Ebenso wichtig ist es, das Fehlerverhalten zu prüfen. In diesem Abschnitt stellen wir dir die notwendigen Werkzeuge vor, um zu testen, ob deine Funktion bei bestimmten Eingaben fehlschlägt und ob die Fehlermeldung den Erwartungen entspricht. Dazu benötigst du zwei weitere Systemfunktionen: <span id="Is_error_type_(Z852)"></span> ==== ist Fehlertyp (Z852) ==== Die Funktion {{Z|Z852}} ist eine integrierte Funktion mit der ZID <code>Z852</code> und benötigt zwei Argumente: * '''Fehler''' – Ein {{Z|Z5}}-Objekt, das bei einem fehlgeschlagenen Aufruf ausgelöst werden kann. Eine Fehlerinstanz hat einen Typ und einen Wert. * '''Fehlertyp''' – Ein Verweis auf einen {{Z|Z50}}, der mit dem als erstes Argument übergebenen Fehlertyp verglichen wird. Ist dies der Fall, gibt die Funktion wahr zurück. <span id="Get_error_thrown_by_function_call_(Z853)"></span> ==== Fehler erhalten, ausgelöst durch Funktionsaufruf (Z853) ==== Die Funktion {{Z|Z853}} ist eine integrierte Funktion mit der ZID <code>Z853</code> und benötigt ein Argument: * '''Funktionsaufruf''' – Ein Funktionsaufruf, der entweder einen erfolgreichen Wert beliebigen Typs zurückgibt oder einen Fehler auslöst. Diese Funktion gibt ein {{Z|Z882}} zurück, wobei an erster Stelle ein {{Z|Z40}} und an zweiter Stelle ein {{Z|Z1}} steht: * Wenn der Funktionsaufruf erfolgreich ist und somit keinen Fehler auslöst, enthält das zurückgegebene Paar an erster Stelle falsch und an zweiter Stelle leer. * Wenn der Funktionsaufruf einen Fehler auslöst, enthält das zurückgegebene Paar an erster Stelle wahr und an zweiter Stelle den abgefangenen Fehler. Um diese Funktion in deinen Kompositionen zu verwenden, musst du möglicherweise die zusätzlichen Funktionen verwenden: * {{Z|Z821}} und * {{Z|Z822}} <span id="Testing_errors"></span> ==== Fehler testen ==== Angenommen, unsere Zielfunktion "verbinde zwei Zeichenketten mit Leerzeichen" oder <code>Z30000</code> löst einen Fehler vom Typ <code>Z30005</code> aus, und wir möchten dieses Verhalten testen. Dazu müssen wir Folgendes tun: * Einen fehlgeschlagenen Funktionsaufruf auslösen * Den Fehler mit der Funktion {{Z|Z853}} erhalten * Mit {{Z|Z852}} prüfen, ob der Fehler den richtigen Typ hat Tests haben zwei Felder: * '''Aufruf''' – Ein Funktionsaufruf, der mit den zu testenden Eingaben eine Ausgabe erzeugt. Dieser Aufruf gibt einen Wert zurück. * '''Ergebnisprüfung''' – Ein Funktionsaufruf, der überprüft, ob der vom vorherigen Aufruf zurückgegebene Wert dem erwarteten Wert entspricht. Das erste Argument dieses Funktionsaufrufs wird automatisch mit dem Rückgabewert des ersten Aufrufs belegt. Für eine Schritt-für-Schritt-Anleitung zum Erstellen von Tests siehe {{ll|Wikifunctions:Introduction#Create_tests}}. In unserem Beispiel können wir es so strukturieren — aber das ist nicht die einzige Möglichkeit! Der Aufruf, der ein {{Z|Z5}}-Objekt zurückgibt: <syntaxhighlight lang="prolog"> error = get_second_element_of_typed_list( get_error_thrown_by( join_strings_by_whitespace( "", "not empty" ) ) ) </syntaxhighlight> Und die Ergebnisprüfung, die das {{Z|Z5}}-Objekt als erstes Argument verwendet: <syntaxhighlight lang="prolog"> is_error_type( error, Z30005 ) </syntaxhighlight> Lass uns das Schritt für Schritt tun: # Um einen Test hinzuzufügen, klicke auf der Funktionsseite in der Tabelle "Tests" auf die Schaltfläche "+". Die Felder "Aufruf" und "Ergebnisprüfung" enthalten bereits vordefinierte Funktionen. Um die Fehler zu testen, müssen wir diese jedoch ändern. # Als Erstes richten wir den Aufruf ein: ## Klicke unter "Aufruf" auf die Schaltfläche "›", um den Funktionsaufruf zu erweitern. ## Bearbeite das Feld unter "Funktion" und suche die Funktion "erhalte zweites Element eines typisierten Paars" und wähle sie aus ## Klicke anschließend neben "typisiertes Paar" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "Fehler erhalten, ausgelöst durch Funktionsaufruf" und wähle sie aus ## Klicke neben "Funktionsaufruf" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "verbinde zwei Zeichenketten mit Leerzeichen" (oder nach ZID <code>Z30000</code>) und wähle sie aus ## Lege nun die Eingaben so fest, dass ein Fehler auftritt: Mindestens eine von ihnen muss leer sein. ## Du kannst jetzt deinen "Aufruf" durch erneutes Klicken auf den Pfeil nach unten wieder ausblenden, wenn du möchtest! # Als Nächstes richten wir die Ergebnisprüfung ein: ## Klicke unter "Ergebnisprüfung" auf die Schaltfläche "›", um den Funktionsaufruf zu erweitern. ## Bearbeite das Feld unter "Funktion" und suche die Funktion "ist Fehlertyp" und wähle sie aus ## Du wirst nun nur noch aufgefordert, das zweite Argument zu konfigurieren. Suche unter "Fehlertyp" nach deinem Fehlertyp <code>Z30005</code> und wähle ihn aus. # Und du bist fertig! Du kannst jetzt auf den kreisförmigen Pfeil im Feld "Implementierungen" klicken und solltest grüne Häkchen sehen. Wenn alles geklappt hat, kannst du deinen Test jetzt speichern. Er sollte folgendermaßen aussehen: [[File:Get error expanded.png|frame|center|alt=Testen eines Fehlers mit den Funktionen Fehler erhalten und ist Fehlertyp in ihrer erweiterten Ansicht|Testen eines Fehlers mit den Funktionen Fehler erhalten und ist Fehlertyp in ihrer erweiterten Ansicht]] [[File:Get error collapsed.png|frame|center|alt=Testen eines Fehlers mit den Funktionen Fehler erhalten und ist Fehlertyp in ihrer reduzierten Ansicht|Testen eines Fehlers mit den Funktionen Fehler erhalten und ist Fehlertyp in ihrer reduzierten Ansicht]] <span id="Creating_actionable_error_messages"></span> === Erstellung handlungsorientierter Fehlermeldungen === Wie oben beschrieben, verfügen Fehlertypen über einen optionalen Schlüssel <code>Z50K3</code>, der eine mehrsprachige Liste von HTML-Zeichenketten enthält. Bei der Darstellung von Informationen zu einem Fehler können die im Fehlertyp hinterlegten Meldungen dazu beitragen, eine klare, präzise, ​​informative, übersetzbare und handlungsorientierte Fehlermeldung zu erstellen. Zu diesem Zweck können Fehlermeldungen Parameter wie <code>$1</code>, <code>$2</code> etc. enthalten, wobei die Ziffer dem Argument des Fehlertyps und dessen Wert in der Fehlerinstanz entspricht. Diese Fehlermeldungen werden in Wikifunctions nach der Ausführung eines Funktionsaufrufs im Dialogfenster "Details" angezeigt. Darüber hinaus werden diese Fehlermeldungen auch in anderen Client-Schnittstellen, wie der Abstrakten Wikipedia, ausgegeben, um den Autoren von Abstrakten Inhalten eine bessere Orientierung zu bieten. [[File:Wikifunctions actionable error message example in the Details dialog.png|thumb|Die Fehlermeldung wird unter Verwendung der HTML-Meldung des Fehlertyps und der Werte der Fehlerargumente generiert.]] [[File:Wikifunctions actionable error message example in Abstract Wikipedia.png|thumb|<span lang="en" dir="ltr" class="mw-content-ltr">When available, the HTML error message is rendered in the Abstract Wikipedia preview section.</span>]] <div lang="en" dir="ltr" class="mw-content-ltr"> Let's use a real example to understand the benefits of HTML error messages: </div> <div lang="en" dir="ltr" class="mw-content-ltr"> The function {{Z|Z37847}} returns the first Lexeme reference given a Wikidata Item reference and a language. When there is no Lexeme for this Item-Language combination, it throws an error of type {{Z|Z28248}}, which has three keys: </div> * <span lang="en" dir="ltr" class="mw-content-ltr">'''Z28248K1''' is the input Wikidata item QID</span> * <span lang="en" dir="ltr" class="mw-content-ltr">'''Z28248K2''' is the connecting property, in this case <code>P5137/item for this sense</code></span> * <span lang="en" dir="ltr" class="mw-content-ltr">'''Z28248K3''' is the language code</span> <div lang="en" dir="ltr" class="mw-content-ltr"> When calling this function for a Wikidata lexeme that doesn't exist, the call will throw an error instance like this: </div> <syntaxhighlight lang="json" highlight="10,12"> { "Z1K1": "Z5", "Z5K1": "Z28248", "Z5K2": { "Z1K1": { "Z1K1": "Z7", "Z7K1": "Z885", "Z885K1": "Z28248" }, "Z28248K1": "Q319", "Z28248K2": "P5137", "Z28248K3": "ast" } } </syntaxhighlight> <div lang="en" dir="ltr" class="mw-content-ltr"> While the error type label indicates: <code>No matching lexeme for item in language</code>, a better error message should indicate: </div> * <span lang="en" dir="ltr" class="mw-content-ltr">which is the failing item,</span> * <span lang="en" dir="ltr" class="mw-content-ltr">which is the language missing, and</span> * <span lang="en" dir="ltr" class="mw-content-ltr">what are the possible ways to fix it.</span> <div lang="en" dir="ltr" class="mw-content-ltr"> The error message <code>Z50K3</code> field can provide this functionality. Whenever an Error Type has an error message for the user language (or any of its fallbacks), the error message shown will be rendered by: </div> # <span lang="en" dir="ltr" class="mw-content-ltr">First, replacing the message parameters with the values of the keys. In our example, any <code>$1</code> will be replaced with the value of <code>Z28248K1</code> ("Q319"), <code>$2</code> with "P5137", and <code>$3</code> with "ast",</span> # <span lang="en" dir="ltr" class="mw-content-ltr">Last, sanitizing and rendering the HTML message.</span> <div lang="en" dir="ltr" class="mw-content-ltr"> So a HTML message like: </div> <syntaxhighlight lang="html"> There is no matching lexeme for the item $1 in "$3".<br> <a href="http://wikidata.org/wiki/$1">Edit in Wikidata</a> </syntaxhighlight> <div lang="en" dir="ltr" class="mw-content-ltr"> Will become: </div> : There is no matching lexeme for the item Q319 in "ast" : [[d:Q319|Edit in Wikidata]] <span id="Debugging_your_implementations"></span> == Debuggen deiner Implementierungen == Manchmal läuft etwas schief. Eine Funktion verhält sich möglicherweise anders als erwartet oder ein Wert erscheint merkwürdig. Implementierungen können mitunter sehr komplex sein, und da sie in einer Spielwiesen-Umgebung ausgeführt werden, kann die Fehlersuche extrem schwierig erscheinen. Um das Verständnis der Vorgänge innerhalb eines Funktionsaufrufs zu erleichtern, bietet Wikifunctions einige Debugging-Werkzeuge. Diese Werkzeuge verändern nicht das Ergebnis einer Funktion, sondern fügen den zurückgegebenen Metadaten zusätzliche Informationen hinzu, die du nach dem Ausführen der Funktion einsehen kannst. Du kannst <code>Wikifunctions.Debug()</code> in deinen Code-Implementierungen oder die Funktion {{Z|Z854}} in deinen Kompositionen verwenden. In diesem Abschnitt erfährst du: * Wie man Debug-Meldungen sowohl aus Code- als auch aus Kompositions-Implementierungen hinzufügt, * Wie man die Metadaten manuell oder über die Benutzeroberfläche untersucht, um diese Protokolle einzusehen. <span id="Debugging_your_code_implementations"></span> === Debuggen deiner Code-Implementierungen === Beim Schreiben von Code, sowohl in JavaScript als auch in Python3, kannst du <code>Wikifunctions.Debug()</code> verwenden, um eine Meldung zu deinem Debug-Protokoll hinzuzufügen und die Ausführung fortzusetzen. {{phab|T441028}} <code>Wikifunctions.Debug()</code> hat einen Parameter, der üblicherweise als Zeichenkette erwartet wird. Jedes andere als Parameter übergebene Objekt wird jedoch direkt in eine Zeichenkette umgewandelt. Um zu unseren Code-Implementierungen für unsere Beispielfunktion "verbinde zwei Zeichenketten mit Leerzeichen" Debug-Protokolle hinzuzufügen, können wir dies in JavaScript tun: <syntaxhighlight lang="JavaScript"> function Z30000( Z30000K1, Z30000K2 ) { if ( trim( Z30000K1 ) === '' ) { Wikifunctions.Debug( `first input is empty "${ Z30000K1 }"` ); Wikifunctions.Error( 'Z30005', [ "Z30000K1", Z30000K1 ] ) } if ( trim( Z30000K2 ) === '' ) { Wikifunctions.Debug( `second input is empty "${ Z30000K2 }"` ); Wikifunctions.Error( 'Z30005', [ "Z30000K2", Z30000K2 ] ) } Wikifunctions.Debug( "both inputs are fine" ); return Z30000K1 + " " + Z30000K2; } </syntaxhighlight> Und das Gleiche in deiner Python3-Implementierung: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): if Z30000K1.strip() == "": Wikifunctions.Debug( 'first input is empty "'+Z30000K1+'"' ) Wikifunctions.Error("Z30005", ["Z30000K1", Z30000K1]) if Z30000K2.strip() == "": Wikifunctions.Debug( 'second input is empty "'+Z30000K2+'"' ) Wikifunctions.Error("Z30005", ["Z30000K2", Z30000K2]) Wikifunctions.Debug( 'both inputs are fine' ) return Z30000K1 + " " + Z30000K2 </syntaxhighlight> Auf diese Weise fügen wir deinen Debug-Protokollen in jedem Fall eine Meldung hinzu: * Schlägt der Funktionsaufruf bei der Überprüfung der ersten oder zweiten Eingabe fehl, ist das Ergebnis der Ausführung ein Fehler, enthält aber einen informativen Protokolleintrag darüber, welcher Zweig den Fehler verursacht hat. * Wenn der Funktionsaufruf erfolgreich ist — weil beide Eingaben gültig sind — gibt der Funktionsaufruf die verbundene Zeichenkette zurück, aber die zurückgegebenen Metadaten enthalten auch ein Debug-Protokoll. <span id="Debugging_your_compositions"></span> === Debuggen deiner Kompositionen === Zur Unterstützung des Debuggens von Kompositionen stellt Wikifunctions die integrierte Funktion {{Z|Z854}} bereit. Mit dieser Funktion kannst du Debug-Meldungen an die Ausführung jedes Funktionsaufrufs anhängen, der die endgültige Ausgabe erzeugt. Die während der Auswertung gesammelten Debug-Protokolle werden als Teil der Ausführungsmetadaten unter dem Schlüssel <code>executorDebugLogs</code> zurückgegeben. <span id="Add_debug_log_to_function_call_(Z854)"></span> ==== Debug-Protokoll zu Funktionsaufruf hinzufügen (Z854) ==== Die Funktion {{Z|Z854}} ist eine integrierte Funktion mit der ZID <code>Z854</code> und benötigt zwei Argumente: * '''Funktionsaufruf''' – Jede Komposition, die du ausführen möchtest. * '''Debug-Protokoll''' – Eine Zeichenketten-Meldung, die protokolliert wird, wenn der angegebene Funktionsaufruf ausgewertet wird. Wenn der umschlossene Funktionsaufruf ausgeführt wird, wird die bereitgestellte Meldung zu den Ausführungsprotokollen hinzugefügt. Wird dieser Funktionsaufruf nicht ausgeführt oder ist seine Ausführung nicht Teil der endgültigen Ausgabe, erscheint sein Debug-Protokoll nicht in den Metadaten des Endergebnisses. Diese integrierte Funktion ist besonders nützlich, wenn du beobachten möchtest: * Welcher Zweig einer Bedingung ausgeführt wurde, oder * Die Reihenfolge der Auswertung in einer Komposition. <span id="Using_Add_debug_log_to_function_call"></span> ==== Verwendung von Debug-Protokoll zu Funktionsaufruf hinzufügen ==== Angenommen, du möchtest zu unserer Beispielfunktion "verbinde zwei Zeichenketten mit Leerzeichen" oder <code>Z30000</code> Debug-Protokolle hinzufügen, sodass für die verschiedenen möglichen Ergebnisse unterschiedliche Meldungen angezeigt werden. Du könntest unsere integrierte Debugging-Funktion wie folgt verwenden: <syntaxhighlight lang="prolog"> if ( is_empty_string( Z30000K1 ), add_debug_log( throw_error( Z30005, ... ), 'failed on first input' ) if( is_empty_string( Z30000K2 ), add_debug_log( throw_error( Z30005, ... ), 'failed on second input' ), add_debug_log( join_with_separator( Z30000K1, Z30000K2, " " ), 'both inputs are ok!' ) ) ) </syntaxhighlight> Dies bewirkt Folgendes: * Wird die Funktion mit einer leeren ersten Eingabe aufgerufen, gibt sie eine Fehlermeldung zurück und die Metadaten enthalten einen Eintrag <code>executorDebugLogs</code> mit dem Protokoll-Eintrag "Fehler bei erster Eingabe". * Wird der Aufruf mit einer leeren zweiten Eingabe aufgerufen, schlägt der Aufruf ebenfalls fehl, die protokollierte Meldung lautet jedoch "Fehler bei zweiter Eingabe". * Bei Aufruf mit gültigen Eingaben gibt die Funktion eine erfolgreiche Antwort zurück und zusätzlich enthalten die Metadaten im Schlüssel <code>executorDebugLogs</code> "Beide Eingaben sind in Ordnung". So würde diese Komposition aussehen: [[File:Add debug log expanded.png|frame|center|alt=Implementierung der Komposition mit Debug-Protokoll hinzufügen, um alle möglichen Ausführungspfade zu protokollieren|Implementierung der Komposition mit Debug-Protokoll hinzufügen, um alle möglichen Ausführungspfade zu protokollieren]] <span id="Accessing_execution_debug_logs"></span> === Zugriff auf Ausführungs-Debug-Protokolle === Unabhängig davon, ob deine Ausführungsprotokolle über <code>Wikifunctions.Debug()</code> oder die integrierte Funktion {{Z|Z854}} hinzugefügt werden, werden sie als Teil der Antwort-Metadaten zurückgegeben. Um die Protokolle zu sehen, klicke nach dem Ausführen deiner Funktion auf die Schaltfläche "Details", die unten im Abschnitt "Ergebnis" erscheint. Die Fehler- und Debug-Informationen werden oben im Dialogfeld "Details" angezeigt. Dies ist das Ergebnis, das du sehen würdest, wenn du die Komposition aus unserem vorherigen Beispiel mit gültigen und ungültigen Eingaben ausführst: {| class="wikitable" | [[File:Execution logs success.png|frameless|center|alt=Funktions-Metadatendialog für eine erfolgreiche Ausführung mit Debug-Protokollen]] | [[File:Execution logs failure.png|frameless|center|alt=Funktions-Metadatendialog für eine fehlgeschlagene Ausführung mit Debug-Protokollen]] |- | Funktions-Metadatendialog für eine erfolgreiche Ausführung: zeigt keine Fehler an, sondern das Protokoll der erfolgreichen Ausführung: ''"Beide Eingaben sind in Ordnung!"'' | Funktions-Metadatendialog für eine fehlgeschlagene Ausführung: zeigt die Fehlerinformationen und das zusätzliche Ausführungsprotokoll für den ersten Fehlerzweig an: ''"Fehler bei erster Eingabe"'' |} [[Category:How to create implementations| {{#translation:}}]] qshy3i6m2kbfg202gscw6300z9txgjn 333944 333942 2026-10-27T19:28:06Z Ameisenigel 44 Created page with "Sofern verfügbar, wird die HTML-Fehlermeldung im Vorschau-Bereich der Abstrakten Wikipedia angezeigt." 333944 wikitext text/x-wiki <languages/> Diese Seite bietet eine detailliertere Anleitung dafür, wie man '''Implementierungen erstellt''' und geht über den Überblick auf {{ll|Wikifunctions:Introduction}} hinaus. <span id="Types_of_Implementations"></span> == Arten von Implementierungen == In Wikifunctions kann eine '''Implementierung''' zwei Hauptformen annehmen: '''Code''' oder '''Komposition'''. Eine Code-Implementierung drückt die Logik der Funktion direkt in einer der verfügbaren Programmiersprachen aus (derzeit Python3 oder JavaScript). Sie ist besonders nützlich, wenn sich das Verhalten der Funktion nicht ohne Weiteres aus bestehenden Wikifunktionen ableiten lässt oder wenn eine präzise Kontrolle über die Datenverarbeitung erforderlich ist. Eine Kompositions-Implementierung definiert die Funktion hingegen vollständig durch die Kombination bestehender Funktionen, ohne dass Code geschrieben werden muss. Kompositionen sind leichter verständlich, wiederverwendbar und lassen sich automatisch in andere Sprachen übersetzen. Sie setzen jedoch voraus, dass geeignete Bausteine ​​bereits vorhanden sind und sind oft weniger leistungsfähig. Prüfe daher zunächst, ob dein Ziel durch Komposition erreicht werden kann. Ist dies nicht möglich oder spielen Leistung oder feingranulare Logik eine Rolle, wähle stattdessen eine Code-Implementierung. Es gibt eine dritte Implementierungsart: '''integrierte Implementierungen'''. Diese werden vom Systemcode ausgeführt und können nicht bearbeitet werden. Höchstwahrscheinlich verfügen alle vordefinierten Funktionen über eine integrierte Implementierung. In solchen Fällen wird beim Öffnen der Implementierungsseite die Meldung ''"{{int|wikilambda-implementation-selector-none}}"'' angezeigt. <span id="Practice_Test-Driven_Development"></span> == Praxis der testgetriebenen Entwicklung == '''Testgetriebene Entwicklung''' oder '''TDD''' ist eine Methode zur Softwareentwicklung, bei der Tests geschrieben werden, bevor der eigentliche Code geschrieben wird. Tests dienen dazu, die Funktionsweise einer Funktion anhand von Beispielen und deren Funktionsweise zu verstehen. In Wikifunctions bietet das Schreiben von Tests als erste Tätigkeit erhebliche Vorteile. Wenn du an einer Implementierung arbeitest, kannst du deinen Code anhand der vorhandenen Tests ausführen, um sicherzustellen, dass er sich wie erwartet verhält. Dadurch lassen sich Fehler frühzeitig erkennen, noch bevor du deine Implementierung veröffentlichst. Tests sind außerdem ein effektives Mittel, um die benötigte Funktion zu beschreiben. Durch das Schreiben von Tests '''kommunizierst du klar das erwartete Verhalten''' und die Community kann bei der Implementierung helfen oder alternative Implementierungen erstellen. Stell dir vor, du möchtest eine Funktion implementieren, die zwei Zeichenketten mit einem Leerzeichen dazwischen verknüpft. Ein einfacher Test dafür könnte so aussehen: <syntaxhighlight lang="prolog"> join_with_space( "Hello", "world" ) => "Hello world" </syntaxhighlight> Sobald du das grundlegende Verhalten definiert hast, ist es wichtig, auch '''an Randfälle zu denken''' — Situationen, in denen die Eingaben so beschaffen sind, dass ein spezielles Verhalten erforderlich sein könnte. Was passiert beispielsweise, wenn deine erste Zeichenkette mit einem Leerzeichen endet oder deine zweite mit einem Leerzeichen beginnt? Soll die Funktion alle vorhandenen Leerzeichen beibehalten und ein weiteres hinzufügen oder ein sauber formatiertes Ergebnis mit nur einem Leerzeichen zwischen den Wörtern zurückgeben? Je nach deinen Anforderungen solltest du einen Test für einen solchen Fall erstellen. Ein Test für diesen Sonderfall könnte beispielsweise einer der folgenden sein — aber nicht beide!: <syntaxhighlight lang="prolog"> join_with_space( "Hello ", " world") => "Hello world" </syntaxhighlight> oder ... <syntaxhighlight lang="prolog"> join_with_space( "Hello ", " world") => "Hello world" </syntaxhighlight> Stell sicher, dass deine Tests alle möglichen Sonderfälle abdecken, und sobald du diese hast, stell sicher, dass sie alle mit der Funktion verbunden sind, indem du sie auswählst und auf "Verbinden" klickst. <span id="Code_implementations"></span> == Code-Implementierungen == [[File:Code implementation.png|thumb|alt=Wikifunctions-Code-Editor, der mit einer Funktionsvorlage initialisiert wurde|Beim Hinzufügen einer neuen Code-Implementierung wird die Funktionsvorlage mit den Funktions- und Argumentnamen initialisiert]] Beim Erstellen einer Implementierung mit Code richtet die Wikifunctions-Benutzeroberfläche einen Code-Editor ein, in dem die ausgewählte Sprache für Syntaxhervorhebung und -validierung aktiviert ist. Sobald die zu implementierende Funktion und die Programmiersprache ausgewählt sind, wird dieser Editor mit der korrekten Funktionsvorlage konfiguriert: '''Entferne oder bearbeite sie nicht!''' Platziere deinen Code innerhalb dieser Funktionssignatur. Falls du Hilfsfunktionen benötigst, kannst du diese einfach in deiner Hauptfunktionsdeklaration deklarieren. <span id="Using_input_types_in_your_code"></span> === Verwendung von Eingabetypen in deinem Code === Die Wikifunctions-Typen {{Z|Z6}} und {{Z|Z40}} können in JavaScript und Python3 wie native Typen verwendet werden. Beispielsweise lässt sich eine Zeichenkette verketten oder ein boolescher Wert direkt in einem logischen Ausdruck verwenden. Um andere Typen in deinen Code-Implementierungen zu verwenden, musst du den jeweiligen Typ genauer untersuchen, herausfinden, ob eine Umwandlung in ein natives Äquivalent existiert, und ihn entsprechend behandeln. Nehmen wir beispielsweise an, wir möchten Python-Code schreiben, der eine Eingabe vom Typ {{Z|Z20420}} verarbeitet. Auf der Seite für diesen Typ sehen wir uns die "Typumwandler in Code" an und suchen nach einem Python-Umwandler. Der Umwandler {{Z|Z20424}} wird auf unsere Datumseingabe angewendet, bevor unser Code ausgeführt wird. Unter "nativer Typ" sehen wir, dass unsere Eingabe ein Python-Dictionary ist, und in der Implementierung können wir die zu erwartenden Schlüssel sehen: <syntaxhighlight lang="python3"> return { 'K1': year, 'K2': month, 'K3': day } </syntaxhighlight> Wenn ein Typ keinen Umwandler besitzt, musst du direkt über seine Schlüssel auf seine Bestandteile zugreifen. Nehmen wir beispielsweise an, deine Funktion <code>Z30000</code> hat einen Eingabeparameter <code>Z30000K1</code> vom Typ {{Z|Z11}}. Dieser Typ besitzt zwei Schlüssel: <code>Z11K1</code> für die Sprache (selbst ein Objekt vom Typ {{Z|Z60}}) und <code>Z11K2</code> für den Zeichenketten-Wert. Das Sprachobjekt hat wiederum einen Schlüssel <code>Z60K1</code> für den Sprachcode. Um also eine Zeichenkette mit dem Sprachcode und dem Text zu erhalten, kannst du folgendes schreiben: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1 ) { // z. B. "de: beliebiger Text" return Z30000K1.Z11K1.Z60K1 + ": " + Z30000K1.Z11K2; } </syntaxhighlight> Für eine Kurzübersicht der verfügbaren Typumwandlungen besuche [[Special:MyLanguage/Wikifunctions:Execution targets#Default type conversion|die Tabelle der Standard-Typumwandlungen]]. <span id="Returning_the_right_outputs"></span> === Rückgabe der richtigen Ausgaben === Ähnlich wie bei der Behandlung von Eingaben müssen auch Ausgaben dem in der Funktionsdefinition angegebenen Typ entsprechen. Einige können wie native Typen behandelt werden; daher wird jede Zeichenketten-Ausgabe in ein Wikifunctions-Objekt {{Z|Z6}} und jeder von deiner Implementierung zurückgegebene native boolesche Wert in ein Wikifunctions-Objekt {{Z|Z40}} umgewandelt. Typen mit "Typumwandlern aus Code" wenden die entsprechende Funktion auf die Ausgabe an, um den benötigten Typ zu erzeugen. Am Beispiel von {{Z|Z20420}} transformiert {{Z|Z20443}} die Ausgabe deiner Implementierung – ein Dictionary mit den Schlüsseln K1, K2 und K3 – in die korrekte ZObjekt-Darstellung. Für Typen, die keine Umwandler aus Code haben, kannst du die Ausgabeobjekte sorgfältig erstellen und zurückgeben. Stell dir beispielsweise vor, unsere Funktion <code>Z30000</code> nimmt zwei Zeichenketten als Eingaben entgegen: Sprachcode und Text, und soll ein Objekt {{Z|Z11}} zurückgeben. In Python kannst du dies mit dem Konstruktor <code>ZObject</code> erreichen: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): lang_object = ZObject( {"Z1K1": "Z9", "Z9K1": "Z60"}, Z60K1 = Z30000K1 ) return ZObject( {"Z1K1": "Z9", "Z9K1": "Z11"}, Z11K1 = lang_object, Z11K2 = Z30000K2 ) </syntaxhighlight> Oder in JavaScript: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1, Z30000K2 ) { const langObject = new ZObject( new Map( [ [ "Z60K1", Z30000K1 ] ] ), { "Z1K1": "Z9", "Z9K1": "Z60" } ); const monolingualKeys = new Map( [ [ "Z11K1", langObject ], [ "Z11K2", Z30000K2 ] ] ); return new ZObject( monolingualKeys, { "Z1K1": "Z9", "Z9K1": "Z11" } ); } </syntaxhighlight> Du kannst mehr über die Klasse <code>ZObject</code> und andere nützliche Konstruktoren auf {{ll|Wikifunctions:Execution_targets#Custom_and_non-built-in_type_conversion}} erfahren. {{phab|T392750}}Stand Mai 2026 kann der Versuch, eine Liste von Listen zurückzugeben, fehlschlagen; daher ist es nicht möglich, solche Funktionen in Code zu implementieren. === Code in Python === In diesem Abschnitt geben wir ein konkretes Beispiel, wie man eine Implementierung in Form von Code in Python erstellt. Angenommen, wir möchten eine Implementierung für eine Funktion erstellen, die zwei Eingabezeichenketten durch Einfügen eines Leerzeichens dazwischen kombiniert und das Ergebnis zurückgibt. Nehmen wir an, die ZID dieser Funktion ist Z30000. Die Implementierung wird über die ZID der Funktion definiert. Das gilt auch für die Argumente der Funktion. Im Fall der Funktion Z30000 mit ihren beiden Argumenten sollte die Funktionsvorlage also so aussehen: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): </syntaxhighlight> Wie bereits erwähnt, wissen wir, dass die Argumente (<code>Z30000K1</code> und <code>Z30000K2</code>) Zeichenketten sind, daher können wir sie genauso behandeln wie native Zeichenketten in Python. Die Funktion sollte außerdem eine Zeichenkette zurückgeben. In unserem Beispiel geben wir einfach die beiden Argumente, getrennt durch ein Leerzeichen, aneinandergereiht zurück: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): return Z30000K1 + " " + Z30000K2 </syntaxhighlight> Da es sich um Python handelt, vergesse nicht, diese Zeile einzurücken. Wenn du unserem Rat gefolgt bist, [[#Practice Test-Driven Development|TDD anzuwenden]], verfügst du bereits über eine Reihe von Tests, von denen du weißt, dass sie funktionieren sollten. In diesem Fall kannst du während der Entwicklung deiner Implementierung auf den kreisförmigen Pfeil im Testbereich klicken und überprüfen, ob deine Implementierung alle Tests besteht. Denke daran, dass die Laufzeit keinen Status hat. Gehe nicht von Werten für globale oder statische Variablen aus. Wenn du weitere Fragen dazu hast, was du in Python tun kannst und was nicht, frage auf [[Wikifunctions:Python implementations]]. === Code in JavaScript === In diesem Abschnitt geben wir ein konkretes Beispiel, wie man eine Implementierung in Form von Code in JavaScript erstellt. Angenommen, wir möchten eine Implementierung für eine Funktion erstellen, die zwei Eingabezeichenketten durch Einfügen eines Leerzeichens dazwischen kombiniert und das Ergebnis zurückgibt. Nehmen wir an, die ZID dieser Funktion ist <code>Z30000</code>. Die Implementierung wird über die ZID der Funktion definiert. Das gilt auch für die Argumente der Funktion. Im Fall der Funktion <code>Z30000</code> mit ihren beiden Argumenten sollte die Funktionsvorlage also so aussehen: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1, Z30000K2 ) { } </syntaxhighlight> Wir wissen, dass die Argumente (<code>Z30000K1</code> und <code>Z30000K2</code>) Zeichenketten sind, daher können wir sie in JavaScript wie native Zeichenketten behandeln. Die Funktion soll außerdem eine Zeichenkette zurückgeben. Um die Funktion zu vervollständigen, kannst du eine Zeile hinzufügen, die die Eingabezeichenketten verkettet, etwa so: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1, Z30000K2 ) { return Z30000K1 + " " + Z30000K2; } </syntaxhighlight> Wenn du Tests wie im Abschnitt [[#Practice Test-Driven Development|TDD]] oben empfohlen hast, klicke auf den kreisförmigen Pfeil im Testbereich und prüfe, ob deine Implementierung alle Tests besteht. Denke daran, dass die Laufzeit keinen Status hat. Gehe nicht von Werten für globale oder statische Variablen aus. Wenn du weitere Fragen dazu hast, was du in JavaScript tun kannst und was nicht, frage auf [[Wikifunctions:JavaScript implementations]]. <span id="Calling_another_Wikifunctions_function"></span> === Aufruf einer anderen Wikifunctions-Funktion === Eine Code-Implementierung kann bestimmte andere Wikifunctions-Funktionen aufrufen, die Ausgabe des Aufrufs empfangen und diese Ausgabe für die weitere Verarbeitung nutzen. Wir bezeichnen solche Aufrufe als Callbacks. Derzeit können aus Sicherheits- und Leistungsgründen nur die folgenden integrierten Wikidata-Abruf- und Suchfunktionen auf diese Weise aufgerufen werden: {{Z|Z6820}}, {{Z|Z6821}}, {{Z|Z6822}}, {{Z|Z6824}}, {{Z|Z6825}}, {{Z|Z6826}}, {{Z|Z6830}} und {{Z|Z6831}}. Diese Funktionalität befindet sich in einem frühen Stadium der Einführung; wir hoffen, in Zukunft Aufrufe für eine größere Bandbreite an Funktionen zu ermöglichen. Betrachten wir eine JavaScript-Implementierung, die einen Callback enthält. Diese Implementierung ruft ein Datenobjekt von Wikidata ab, extrahiert die Bezeichnung dieses Datenobjektes in einer bestimmten Sprache und gibt die Bezeichnung als Zeichenkette zurück. Das abzurufende Datenobjekt wird über das Argument <code>Z400K1</code> angegeben, die Sprache über <code>Z400K2</code>. <syntaxhighlight lang="javascript"> function Z400( Z400K1, Z400K2 ) { const item = Wikifunctions.Call('Z6821', Z400K1); for (const label of item.Z6001K2.Z12K1) { if (label.Z11K1.Z60K1 === Z400K2.Z60K1) { return label.Z11K2; }} return 'NOT FOUND'; } </syntaxhighlight> Ein Callback wird durch den Aufruf von <code>Wikifunctions.Call</code> ausgelöst, wie im Beispiel gezeigt. Das erste Argument für <code>Wikifunctions.Call</code> ist stets die ZID der aufzurufenden Funktion – in diesem Fall {{Z|Z6821}}, welche ein einzelnes Argument entgegennimmt. Darauf folgen, durch Kommas getrennt, die an diese Funktion zu übergebenden Argumente. Hierbei handelt es sich bei dem Argument <code>Z400K1</code> um denselben Wert, der auch an <code>Z400</code> übergeben wurde. Dies ist ein gängiges Muster für die Argumentübergabe an Callbacks, jedoch können die Argumente auch mit dem Konstruktor <code>ZObject</code> (wie oben beschrieben) erstellt oder auf andere Weise bezogen werden. Der Wert von <code>Z400K1</code> wäre eine Instanz von {{Z|Z6091}}, die die QID des abzurufenden Datenobjekts enthält. Zeile 2 des Beispiels ruft <code>Z6821</code> auf, um dieses Datenobjekt von Wikidata abzurufen, und weist das resultierende ZObjekt der Konstante <code>item</code> zu. Der restliche Code durchläuft die Bezeichnungen des Datenobjekts, bis er diejenige findet, die der durch <code>Z400K2</code> angegebenen Sprache entspricht. Für das obige Beispiel haben wir der Einfachheit halber <code>Z6821</code> verwendet. Sofern die Implementierung jedoch nicht das gesamte Objekt benötigt, wird dringend empfohlen, zum Abrufen von Wikidata-Datenobjekten, die sehr groß sein können, <code>Z6820</code> zu verwenden. Obwohl der Aufruf von <code>Z6820</code> etwas komplexer ist, ermöglichen seine Parameter das Abrufen spezifischer Teile eines Wikidata-Datenobjekts. Dies kann die Leistung erheblich steigern und bestimmte Fehler vermeiden, da weniger Netzwerkbandbreite und Verarbeitungszeit erforderlich sind. (<code>Z6820</code> kann auch statt <code>Z6822</code>, <code>Z6824</code>, <code>Z6825</code> und <code>Z6826</code> verwendet werden, um ähnliche Vorteile bei der Bandweitenreduzierung zu erreichen.) Im Folgenden zeigen wir, wie <code>Z6820</code> in <code>Wikifunctions.Call</code> verwendet werden kann, um dasselbe Verhalten wie oben zu erzielen. Beachte, dass wir das zweite an <code>Z6820</code> übergebene Argument, <code>[labelsPart]</code>, nutzen, um festzulegen: “Gib nur die Bezeichnungen des Datenobjekts zurück”, und das dritte Argument, <code>[Z400K2]</code>, verwenden, um festzulegen: “Gib die Bezeichnungen nur in der angegebenen Sprache zurück”. (Dieses Argument würde auch für Aliasse und Beschreibungen gelten, sofern diese im Ergebnis enthalten wären.) <syntaxhighlight lang="javascript"> function Z400( Z400K1, Z400K2 ) { const labelsPart = new ZObject( new Map( [ ['Z6030K1', new ZReference('Z6033')] ] ), {Z1K1: 'Z9', Z9K1: 'Z6030'} ); const entities = Wikifunctions.Call( 'Z6820', [Z400K1], [labelsPart], [Z400K2], []); const item = entities.get(Z400K1.Z6091K1); const labels = item.Z6001K2.Z12K1; for (const label of labels) { if (label.Z11K1.Z60K1 === Z400K2.Z60K1) { return label.Z11K2; }} return 'NOT FOUND'; } </syntaxhighlight> Weitere zu beachtende Hinweise: * Obwohl Code-Implementierungen mittlerweile in der Lage sind, Wikidata-Entitäten abzurufen, wird empfohlen, dass sie keine ''vollständigen'' Entitäten zurückgeben. Dies liegt an den derzeitigen Beschränkungen hinsichtlich der Größe des von einer Code-Implementierung zurückgegebenen Wertes. Um eine vollständige, große Entität abzurufen und zurückzugeben, ist es besser, die Abruffunktion aus einer Komposition heraus aufzurufen. * Es kann nur ein Callback gleichzeitig ausgeführt werden. Aus Sicherheitsgründen ist es nicht möglich, die Nebenläufigkeitsfunktionen von JavaScript oder Python zu nutzen, um mehrere Callbacks parallel auszuführen. ** Beachte jedoch, dass du mithilfe von Z6820 mehrere Entitäten auf einmal abrufen kannst. * Derzeit gibt es eine Obergrenze von 3 MiB für die Größe von Wikidata-Inhalten, die über einen einzelnen Callback an eine Code-Implementierung zurückgegeben werden können. Dieselbe Obergrenze gilt für die Größe des Ergebnisses, das von einer Code-Implementierung zurückgegeben wird. <span id="Compositions"></span> == Kompositionen == Im diesem Abschnitt geben wir ein konkretes Beispiel, wie man eine Implementierung in Form einer Komposition erstellt. Angenommen, wir möchten eine Implementierung für eine Funktion erstellen, die zwei Eingabezeichenketten durch Einfügen eines Leerzeichens dazwischen kombiniert und das Ergebnis zurückgibt. Nehmen wir an, die ZID dieser Funktion ist <code>Z30000</code>. Normalerweise ist es sinnvoll, zunächst darüber nachzudenken, wie man vorhandene Funktionen kombinieren kann, um die gewünschte Ausgabe zu erzielen. Manchmal mag dies trivial sein und du kannst einfach mit dem Zusammenstellen und Funktionen fortfahren, aber in vielen Fällen lohnt es sich, die gewünschte Komposition zu notieren. Beispielsweise könnten wir für die angegebene Funktion die vorhandene Funktion {{Z|Z10000}} verwenden. Diese Funktion nimmt zwei Zeichenketten und erstellt daraus eine Zeichenkette. Aber wir müssen dazwischen ein Leerzeichen einfügen. Wir verbinden also zunächst ein Leerzeichen mit dem Ende der ersten Zeichenkette und verbinden dann die zweite Zeichenfolge mit dem Ergebnis dieser ersten Verbindung. Unsere Komposition könnte also so notiert werden: <syntaxhighlight lang="prolog"> join_strings( join_strings( Z30000K1, " " ), Z30000K2 ) </syntaxhighlight> Es gibt mehrere Möglichkeiten, eine Komposition zu schreiben: Beachte, dass dasselbe auch auf folgende Weise erreicht werden kann: <syntaxhighlight lang="prolog"> join_strings( Z30000K1, join_strings( " ", Z30000K2 ) ) </syntaxhighlight> Eine alternative Implementierung könnte auch die vorhandene Funktion {{Z|Z15175}} verwenden, sodass deine Komposition wie folgt aussehen könnte: <syntaxhighlight lang="prolog"> join_with_separator( Z30000K1, Z30000K2, " " ) </syntaxhighlight> Wie du siehst, gibt es mehrere Möglichkeiten, dies zu erreichen. Nimm dir also Zeit und erkunde die vorhandenen Funktionen, die im {{ll|Wikifunctions:Catalogue}} verfügbar sind. Versuchen wir, das zweite Beispiel zu erstellen, <code>join_strings(Z30000K1, join_strings(" ", Z30000K2))</code>. Um dies zu erstellen: # Um eine Implementierung hinzuzufügen, klicke auf der Funktionsseite in der Tabelle "Implementierungen" auf die Schaltfläche "+". # Stelle sicher, dass die Option "Komposition" unter "Implementierung" ausgewählt ist. # Klicke auf das Symbol "›" oder auf den Link "Funktion auswählen", um die Funktionsdetails anzuzeigen. # Suche unter "Funktion" nach dem Namen der äußersten Funktion, die du verwenden möchtest, in diesem Beispiel "verbinde Zeichenketten". Wähle anschließend die gewünschte Funktion aus der Dropdown-Liste aus. # Du siehst zwei neue Felder, eines für jedes der Argumente, die für die ausgewählte Funktion benötigt werden. # Als erstes Argument möchten wir den ersten Eingabewert für unsere Funktion auswählen: ## Klicke neben "erste Zeichenkette" auf die Schaltfläche "…" und wähle "Argumentreferenz" aus. ## Unter "Schlüssel-ID" kannst du nun die erste Zeichenkette deiner Funktion aus dem Dropdown-Menü auswählen, das alle verfügbaren Eingaben enthält. # Für das zweite Argument möchten wir das Ergebnis eines weiteren Aufrufs von "verbinde Zeichenketten" verwenden: ## Klicke neben "zweite Zeichenkette" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus. ## Suche unter "Funktion" nach der Funktion, die du aufrufen möchtest und wähle sie aus, nämlich "verbinde Zeichenketten". ## Konfiguriere die "erste Zeichenkette" für diesen inneren Funktionsaufruf, indem du einfach ein Leerzeichen in das Textfeld eingibst, und konfiguriere die "zweite Zeichenkette" wie in Schritt 6: Ändere sie mit der Schaltfläche "…" in "Argumentreferenz" und wähle dann das zweite Argument in der Dropdown-Liste aus. Deine Komposition ist nun fertig! Du kannst die Details mithilfe der Pfeiltasten ein- und ausblenden, um dir einen Überblick zu verschaffen. Falls du bereits Tests wie im Abschnitt [[#Practice Test-Driven Development|TDD]] oben empfohlen implementiert hast, klicke im Testbereich auf den kreisförmigen Pfeil und prüfe, ob deine Implementierung die Tests besteht. Sobald deine Komposition die Tests bestanden hat, kannst du sie veröffentlichen. [[File:Composition implementation expanded.png|frame|center|alt=Eine Wikifunctions-Kompositionsimplementierung in ihrer erweiterten Ansicht|Eine Wikifunctions-Kompositionsimplementierung in ihrer erweiterten Ansicht]] [[File:Composition implementation collapsed.png|frame|center|alt=Eine Wikifunctions-Kompositionsimplementierung in ihrer reduzierten Ansicht|Eine Wikifunctions-Kompositionsimplementierung in ihrer reduzierten Ansicht]] <span id="Wikifunctions_error_handling"></span> == Fehlerbehandlung auf Wikifunctions == Als Ersteller einer Wikifunctions-Funktion möchtest du möglicherweise den Benutzer warnen, der deine Funktion aufruft, wenn im Code ein Fehler auftritt oder seine Eingaben bestimmte Kriterien nicht erfüllen. Wenn deine Funktion beispielsweise eine Zeichenkette mit einem Namen erwartet, solltest du prüfen, ob der Name nicht leer ist, und gegebenenfalls eine verständliche Fehlermeldung anzeigen. Hierfür kannst du <code>Wikifunctions.Error()</code> in deinen Code-Implementierungen oder die Funktion {{Z|Z851}} in deinen Kompositionen verwenden. In diesem Abschnitt erfährst du: * Wie man Fehler sowohl aus Code- als auch aus Kompositions-Implementierungen auslöst, * wie man Tests für Fehlerfälle schreibt, und * wie man Fehler abfängt und behandelt, die von Funktionen ausgelöst werden, die man in seinen Kompositionen verwendet. <span id="Throwing_errors_from_code_implementations"></span> === Fehler aus Code-Implementierungen auslösen === Sowohl beim Schreiben von JavaScript- als auch von Python-Code kannst du <code>Wikifunctions.Error()</code> nutzen, um die Ausführung mit einem gewünschten Fehler zu beenden. <code>Wikifunctions.Error()</code> hat zwei Parameter: # Fehlertyp: Eine Zeichenkette, die die ZID des Fehlertyps enthält, den du zurückgeben möchtest. # Fehlerargumente: Eine Liste von Zeichenkettenargumenten zur Erstellung des Fehlers. Gehen wir sie der Reihe nach durch: <span id="Error_type"></span> ==== Fehlertyp ==== Ein Fehlertyp ist ein Objekt, das eine Art von Fehler beschreibt, der im System auftreten kann. Es gibt eine Reihe vordefinierter Fehlertypen, du kannst aber auch eigene Fehlertypen erstellen, die besser zu deinem Anwendungsfall passen. Bei der Verwendung von Fehlern empfiehlt es sich, die verfügbaren Fehlertypen zu durchsuchen, die sich in [[Special:ListObjectsByType/Z50|dieser Liste]] finden. Falls keine passenden Fehler für deinen Fall vorhanden sind, erstelle einen neuen Fehler, indem du zur Erstellungsseite gehst und im Typauswahlfeld "Fehlertyp" auswählst. Lege anschließend die erforderlichen Felder fest: [[File:Error type.png|thumb|alt=Erstellung von Fehlertypen in Wikifunctions|Um einen neuen Fehlertyp (Z50) zu erstellen, bearbeite die Bezeichnung und füge die erforderlichen Schlüssel hinzu.]] * '''Bezeichnung''' – Dies ist der Haupttitel des Fehlers, der eine kurze, aber aussagekräftige Meldung enthalten sollte. Lege die Fehlerbezeichnung im rechten Feld mit dem Titel "Info" fest. * '''Schlüssel''' – Schlüssel enthalten zusätzliche Informationen zur Fehlerursache. Wenn beispielsweise eine Eingabe das falsche Format aufwies, möchtest du den Benutzer möglicherweise über den eingegebenen Inhalt informieren, wenn der Fehler auftritt. Um sie in deinen Implementierungen zu verwenden, müssen Schlüssel vom Zeichenketten sein. Um einen Schlüssel zu erstellen, klicke auf das Symbol "[+]" unterhalb von "Schlüssel", wähle unter "Werttyp" die Option "Zeichenkette" aus und füge eine aussagekräftige Bezeichnung hinzu, beispielsweise "tatsächlich Eingabe". Sobald du alle erforderlichen Schlüssel erstellt hast, kannst du deinen Fehlertyp veröffentlichen und die ID des neu erstellten Objekts speichern. * '''Fehlermeldung''' – Fehlertypen können ein mehrsprachiges Array von Fehlermeldungen enthalten, die mit HTML-Parametern versehen sind. Die Parameter werden als $1, $2 etc. angegeben, wobei die Ziffer dem Schlüssel des Fehlertyps entspricht. Beim Erstellen eines Fehlertyps mit dem Zeichenketten-Schlüssel "aktuelle Eingabe", kann die Fehlermeldung beispielsweise den Platzhalter "$1" verwenden, der zum Zeitpunkt der Fehlerausgabe durch den Wert des Schlüssels "aktuelle Eingabe" ersetzt wird. Um HTML-Meldungen hinzuzufügen, klicke unter "HTML-Fragmente" auf das Symbol "[+]", wähle eine Sprache aus und gib die HTML-Zeichenkette ein. <span id="Error_arguments"></span> ==== Fehlerargumente ==== Fehlerargumente entsprechen den Schlüsseln des Fehlertyps und sollten zusätzliche Informationen zum Verständnis des Fehlers liefern. Fehlerargumente sollten immer Zeichenketten sein. <span id="Using_Wikifunctions.Error()"></span> ==== Verwendung von Wikifunctions.Error() ==== Angenommen, du möchtest einen Fehler auslösen, wenn entweder deine erste oder deine zweite Eingabe leer ist. Du hast den Fehlertyp bereits erstellt und ihm wurde die ZID <code>Z30005</code> zugewiesen. Dein Fehlertyp hat zwei Zeichenketten-Schlüssel: * Eingabeschlüssel: Enthält den Schlüssel der fehlerhaften Eingabe * Eingabewert: Enthält den aktuellen Wert der fehlerhaften Eingabe Um einen Fehler in deiner JavaScript-Implementierung auszulösen, solltest du etwa Folgendes tun: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1, Z30000K2 ) { if ( trim( Z30000K1 ) === '' ) { // Wenn die erste Eingabe leer ist, löse Fehler Z30005 aus // mit zwei Zeichenketten-Argumenten: [ erster Eingabe-Schlüssel, erster Eingabe-Wert ] Wikifunctions.Error( 'Z30005', [ "Z30000K1", Z30000K1 ] ) } if ( trim( Z30000K2 ) === '' ) { // Wenn die zweite Eingabe leer ist, löse Fehler Z30005 aus // mit zwei Zeichenketten-Argumenten: [ zweiter Eingabe-Schlüssel, zweiter Eingabe-Wert ] Wikifunctions.Error( 'Z30005', [ "Z30000K2", Z30000K2 ] ) } return Z30000K1 + " " + Z30000K2; } </syntaxhighlight> Um einen Fehler in deiner Python-Implementierung auszulösen, solltest du etwa Folgendes tun: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): if Z30000K1.strip() == "": # Wenn die erste Eingabe leer ist, löse Fehler Z30005 aus # mit zwei Zeichenketten-Argumenten: [ erster Eingabe-Schlüssel, erster Eingabe-Wert ] Wikifunctions.Error("Z30005", ["Z30000K1", Z30000K1]) if Z30000K2.strip() == "": # Wenn die zweite Eingabe leer ist, löse Fehler Z30005 aus # mit zwei Zeichenketten-Argumenten: [ erster Eingabe-Schlüssel, erster Eingabe-Wert ] Wikifunctions.Error("Z30005", ["Z30000K2", Z30000K2]) return Z30000K1 + " " + Z30000K2 </syntaxhighlight> Denke daran, dass der Aufruf von <code>Wikifunctions.Error()</code> die Ausführung beendet! <span id="Throwing_errors_from_compositions"></span> === Fehler aus Kompositionen auslösen === Wenn du eine Kompositionsimplementierung erstellst, kannst du einen Fehler auslösen, indem du die Spezialfunktion {{Z|Z851}} aufrufst. <span id="Throw_Error_function_(Z851)"></span> ==== Funktion Fehler auslösen (Z851) ==== Die Funktion {{Z|Z851}} ähnelt der Methode <code>Wikifunctions.Error()</code> und benötigt zwei Argumente: * '''Fehlertyp''' – Ein Verweis auf den Fehlertyp, den du auslösen möchtest * '''Fehlerparameter''' – Eine Liste mit den Argumenten zur Erstellung deines Fehlers, die ebenfalls Zeichenketten sein sollten. <span id="Using_Throw_Error"></span> ==== Verwendung von Fehler auslösen ==== Angenommen, du möchtest deine Komposition so ändern, dass sie zuerst prüft, ob die Argumente nicht leer sind, und einen Fehler ausgibt, wenn sie ein leeres Argument findet. Wenn dann keines der Argumente leer ist, wird die ursprüngliche Komposition ausgeführt, die wie folgt aussieht: <syntaxhighlight lang="prolog"> join_with_separator( Z30000K1, Z30000K2, " " ) </syntaxhighlight> Dazu musst du bedingte Pfade erstellen, für die du die Funktion {{Z|Z802}} verwenden kannst. Stell es dir folgendermaßen vor: * Wenn das erste Argument leer ist, soll ein Fehler für das erste Argument ausgelöst werden * Andernfalls wird mit der Überprüfung des zweiten Arguments fortgefahren * Wenn das zweite Argument leer ist, soll ein Fehler für das zweite Argument ausgelöst werden * Andernfalls wird der Erfolgspfad verfolgt und die verbundenen Zeichenketten mit dem Leerzeichen als Trennzeichen zurückgegeben Oder in funktionalem Pseudocode: <syntaxhighlight lang="prolog"> if ( is_empty_string( Z30000K1 ), throw_error( Z30005, [ "Z30000K1", Z30000K1 ] ), if( is_empty_string( Z30000K2 ), throw_error( Z30005, [ "Z30000K2", Z30000K2 ] ), join_with_separator( Z30000K1, Z30000K2, " " ) ) ) </syntaxhighlight> Lass uns das Schritt für Schritt erstellen: # Um eine Implementierung hinzuzufügen, klicke auf der Funktionsseite in der Tabelle "Implementierungen" auf die Schaltfläche "+". # Stelle sicher, dass die Option "Komposition" unter "Implementierung" ausgewählt ist. # Klicke auf das Symbol "›" oder auf den Link "Funktion auswählen", um die Funktionsdetails anzuzeigen. # Suche unter "Funktion" nach der äußersten Funktion, die du verwenden möchtest, in diesem Fall "wenn", und wähle sie aus. # Überprüfe die Gültigkeit des ersten Arguments: ## Klicke neben "Bedingung" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "ist leere Zeichenkette" und wähle sie aus ## Klicke neben "Eingabe" auf die Schaltfläche "…" und wähle "Argumentreferenz" aus ## Wähle unter "Schlüssel-ID" die erste Eingabe aus (z. B. "erste Zeichenkette") ## Du kannst den Funktionsaufruf der "Bedingung" nun bei Bedarf ausblenden, indem du auf den Pfeil nach unten neben "Bedingung" klickst. Es sollte dann etwa Folgendes angezeigt werden: "f(x) ist leere Zeichenkette ( → erste Zeichenkette )" # Fehler auslösen, wenn die Bedingung wahr ist: ## Klicke neben "dann" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "Fehler auslösen" und wähle sie aus ## Suche unter "Fehlertyp" nach deinem Fehlertyp (du kannst die Fehler-ID direkt eingeben, wenn du sie kennst, z. B. Z30005) und wähle ihn aus ## Füge unter "Fehlerparameter" zwei Elemente hinzu, indem du auf die Schaltfläche "+" klickst ## Lege für "Objekt 1" (fehlerhafter Argumentschlüssel) den Typ auf "Zeichenkette" fest und trage die Argumentkennung ein (z. B. "erste Eingabe" oder "Z30000K1") ## Klicke für "Objekt 2" (fehlerhafter Argumentwert) auf die "…" neben "Objekt 2" und wähle "Argumentreferenz" aus ## Wähle unter "Schlüssel-ID" die erste Eingabe aus (z. B. "erste Zeichenkette") ## Du kannst den Funktionsaufruf "dann" nun bei Bedarf ausblenden, indem du auf den Pfeil nach unten neben "dann" klickst. Es sollte dann etwa Folgendes angezeigt werden: "f(x) Fehler auslösen ( ungültiges Format, typisierte Liste ( Objekt, "erste Eingabe", → erste Zeichenkette ) )" # Prüfe das zweite Argument, wenn das erste korrekt war: ## Klicke neben "sonst" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "wenn" und wähle sie aus ## Richte eine "Bedingung" ein, um die Gültigkeit des zweiten Arguments zu überprüfen, indem du das gleiche Verfahren wie in Schritt 5 beschrieben anwendest. ## Richte "dann" so ein, dass beim zweiten Argument ein Fehler ausgelöst wird, indem du das gleiche Verfahren wie in Schritt 6 beschrieben anwendest. # Richte schließlich den Erfolgspfad ein: ## Klicke neben dem verschachtelten "sonst" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der gewünschten Funktion, in diesem Fall "vereinige zwei Zeichenketten mit Trennzeichen", und wähle sie aus ## Klicke neben "erste Zeichenkette" auf die Schaltfläche "…" und setze sie auf "Argumentreferenz", wähle anschließend "erste Zeichenkette" aus ## Klicke neben "zweite Zeichenkette" auf die Schaltfläche "…" und setze sie auf "Argumentreferenz", wähle anschließend "zweite Zeichenkette" aus ## Füge unter "Trennzeichen" ein Leerzeichen in das Textfeld ein Der resultierende Funktionsaufruf sollte folgendermaßen aussehen: [[File:Throw error expanded.png|frame|center|alt=Wikifunctions-Komposition mit der Funktion Fehler auslösen|Wikifunctions-Komposition mit der Funktion Fehler auslösen]] [[File:Throw error collapsed.png|frame|center|alt=Wikifunctions-Komposition mit der Funktion Fehler auslösen in ihrer reduzierten Ansicht|Wikifunctions-Komposition mit der Funktion Fehler auslösen in ihrer reduzierten Ansicht]] <span id="Handling_errors_in_compositions"></span> === Fehlerbehandlung in Kompositionen === Es ist zwar nützlich, Funktionen das Auslösen erwarteter Fehler zu ermöglichen, aber es ist entscheidend, Fehler in den eigenen Kompositionen behandeln zu können, um diese Funktionen sicher verwenden zu können. Angenommen, du möchtest eine neue Funktion "vollständiger Name einer Person" erstellen – wir bezeichnen sie mit der ZID <code>Z30010</code>. Diese Funktion soll den vollständigen Namen einer Person anhand ihres Vor- und Nachnamens zurückgeben. Ist jedoch eines der beiden Felder leer, soll sie stattdessen den Text "Unbekannt" zurückgeben. Du könntest eine Komposition erstellen, indem du unsere Beispielfunktion "verbinde zwei Zeichenketten mit Leerzeichen" oder <code>Z30000</code> verwendest, um den Namen zu generieren. Wenn eine der Eingaben leer ist, weißt du, dass <code>Z30000</code> einen Fehler vom Typ <code>Z30005</code> auslöst. Mithilfe der Funktion {{Z|Z850}} als Wrapper kannst du die Verbindungsoperation ausführen und einen möglichen Fehler abfangen, indem du einfach "Unbekannt" zurückgibst, wenn er auftritt. <span id="Try-Catch_function_(Z850)"></span> ==== Try-Catch-Funktion (Z850) ==== Die Funktion {{Z|Z850}} ist eine integrierte Funktion mit der ZID <code>Z850</code> und benötigt drei Argumente: * '''Funktionsaufruf''' – Der erste Funktionsaufruf, der ausgeführt werden soll. Wenn kein Fehler auftritt, ist die Antwort das Ergebnis dieses Funktionsaufrufs. * '''Fehlertyp''' – Ein Fehlertyp, der abgefangen werden soll, falls er während der Ausführung des ersten Funktionsaufrufs auftritt. * '''Fehlerhandler''' – Ein Funktionsaufruf, der ausgeführt wird, falls der oben genannte Fehler während der Ausführung des ursprünglichen Funktionsaufrufs auftritt. In diesem Fall wird das Ergebnis der Fehlerbehandlung zurückgegeben. <span id="Using_Try-Catch"></span> ==== Verwendung der Try-Catch-Funktion ==== Sobald wir alle Funktionen für unsere Komposition haben, können wir sie folgendermaßen gestalten: <syntaxhighlight lang="prolog"> try_catch( join_with_space( Z30010K1, Z30010K2 ), Z30005, echo( "Unknown" ) ) </syntaxhighlight> Das bedeutet: * Die Funktion "verbinde zwei Zeichenketten mit Leerzeichen" wird mit den beiden Eingaben ausprobiert und wenn alles erfolgreich verläuft, wird das Ergebnis dieser Funktion zurückgegeben * Wenn eine der Eingaben leer ist, löst "verbinde zwei Zeichenketten mit Leerzeichen" einen Fehler vom Typ <code>Z30005</code> aus * Unsere {{Z|Z850}} erkennt dann diesen Fehler und führt die Funktion {{Z|Z801}} aus, die "Unbekannt" zurückgibt Lass uns das Schritt für Schritt erstellen: # Um eine Implementierung hinzuzufügen, klicke auf der Funktionsseite in der Tabelle "Implementierungen" auf die Schaltfläche "+". # Stelle sicher, dass die Option "Komposition" unter "Implementierung" ausgewählt ist. # Klicke auf das Symbol "›" oder auf den Link "Funktion auswählen", um die Funktionsdetails anzuzeigen. # Suche unter "Funktion" nach der äußersten Funktion, die du verwenden möchtest, in diesem Fall "Try-Catch-Funktion", und wähle sie aus. # Richte den Hauptfunktionsaufruf ein: ## Klicke unterhalb des Feldes, in dem die "Try-Catch-Funktion" ausgewählt ist, neben dem Schlüssel "Funktionsaufruf" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "verbinde zwei Zeichenketten mit Leerzeichen" und wähle sie aus ## Klicke neben "erste Zeichenkette" auf die Schaltfläche "…" und wähle "Argumentreferenz" aus, wähle anschließend das Argument "erster Name" aus der Dropdown-Liste aus. ## Klicke neben "zweite Zeichenkette" auf die Schaltfläche "…" und wähle "Argumentreferenz" aus, wähle anschließend das Argument "zweiter Name" aus der Dropdown-Liste aus. # Wähle den abzufangenden Fehler aus: ## Suche unter "Fehlertyp" nach "ungültige Zeichenkette" und wähle es aus – du kannst direkt nach der ZID <code>Z30005</code> suchen # Richte den Funktionsaufruf für den Fehlerhandler ein: ## Klicke neben "Fehlerhandler" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "Echo" und wähle sie aus ## Suche unter "Eingabe" und "Typ" den Typ "Zeichenkette" und wähle ihn aus ## Gib nun unter "Eingabe" im Textfeld "Unbekannt" ein Die resultierende Funktion sollte folgendermaßen aussehen: [[File:Try catch expanded.png|frame|center|alt=Wikifunctions-Komposition mit der Try-Catch-Funktion in ihrer erweiterten Ansicht|Wikifunctions-Komposition mit der Try-Catch-Funktion in ihrer erweiterten Ansicht]] [[File:Try catch collapsed.png|frame|center|alt=Wikifunctions-Komposition mit der Try-Catch-Funktion in ihrer reduzierten Ansicht|Wikifunctions-Komposition mit der Try-Catch-Funktion in ihrer reduzierten Ansicht]] <span id="Testing_your_failure_use_cases"></span> === Testen deiner Fehlerfälle === Wie bereits im Abschnitt über die [[#Practice Test-Driven Development|Anwendung von TDD]] erläutert, ist es wichtig, nicht nur die häufigsten Ausführungspfade, sondern auch mögliche Randfälle zu testen. Ebenso wichtig ist es, das Fehlerverhalten zu prüfen. In diesem Abschnitt stellen wir dir die notwendigen Werkzeuge vor, um zu testen, ob deine Funktion bei bestimmten Eingaben fehlschlägt und ob die Fehlermeldung den Erwartungen entspricht. Dazu benötigst du zwei weitere Systemfunktionen: <span id="Is_error_type_(Z852)"></span> ==== ist Fehlertyp (Z852) ==== Die Funktion {{Z|Z852}} ist eine integrierte Funktion mit der ZID <code>Z852</code> und benötigt zwei Argumente: * '''Fehler''' – Ein {{Z|Z5}}-Objekt, das bei einem fehlgeschlagenen Aufruf ausgelöst werden kann. Eine Fehlerinstanz hat einen Typ und einen Wert. * '''Fehlertyp''' – Ein Verweis auf einen {{Z|Z50}}, der mit dem als erstes Argument übergebenen Fehlertyp verglichen wird. Ist dies der Fall, gibt die Funktion wahr zurück. <span id="Get_error_thrown_by_function_call_(Z853)"></span> ==== Fehler erhalten, ausgelöst durch Funktionsaufruf (Z853) ==== Die Funktion {{Z|Z853}} ist eine integrierte Funktion mit der ZID <code>Z853</code> und benötigt ein Argument: * '''Funktionsaufruf''' – Ein Funktionsaufruf, der entweder einen erfolgreichen Wert beliebigen Typs zurückgibt oder einen Fehler auslöst. Diese Funktion gibt ein {{Z|Z882}} zurück, wobei an erster Stelle ein {{Z|Z40}} und an zweiter Stelle ein {{Z|Z1}} steht: * Wenn der Funktionsaufruf erfolgreich ist und somit keinen Fehler auslöst, enthält das zurückgegebene Paar an erster Stelle falsch und an zweiter Stelle leer. * Wenn der Funktionsaufruf einen Fehler auslöst, enthält das zurückgegebene Paar an erster Stelle wahr und an zweiter Stelle den abgefangenen Fehler. Um diese Funktion in deinen Kompositionen zu verwenden, musst du möglicherweise die zusätzlichen Funktionen verwenden: * {{Z|Z821}} und * {{Z|Z822}} <span id="Testing_errors"></span> ==== Fehler testen ==== Angenommen, unsere Zielfunktion "verbinde zwei Zeichenketten mit Leerzeichen" oder <code>Z30000</code> löst einen Fehler vom Typ <code>Z30005</code> aus, und wir möchten dieses Verhalten testen. Dazu müssen wir Folgendes tun: * Einen fehlgeschlagenen Funktionsaufruf auslösen * Den Fehler mit der Funktion {{Z|Z853}} erhalten * Mit {{Z|Z852}} prüfen, ob der Fehler den richtigen Typ hat Tests haben zwei Felder: * '''Aufruf''' – Ein Funktionsaufruf, der mit den zu testenden Eingaben eine Ausgabe erzeugt. Dieser Aufruf gibt einen Wert zurück. * '''Ergebnisprüfung''' – Ein Funktionsaufruf, der überprüft, ob der vom vorherigen Aufruf zurückgegebene Wert dem erwarteten Wert entspricht. Das erste Argument dieses Funktionsaufrufs wird automatisch mit dem Rückgabewert des ersten Aufrufs belegt. Für eine Schritt-für-Schritt-Anleitung zum Erstellen von Tests siehe {{ll|Wikifunctions:Introduction#Create_tests}}. In unserem Beispiel können wir es so strukturieren — aber das ist nicht die einzige Möglichkeit! Der Aufruf, der ein {{Z|Z5}}-Objekt zurückgibt: <syntaxhighlight lang="prolog"> error = get_second_element_of_typed_list( get_error_thrown_by( join_strings_by_whitespace( "", "not empty" ) ) ) </syntaxhighlight> Und die Ergebnisprüfung, die das {{Z|Z5}}-Objekt als erstes Argument verwendet: <syntaxhighlight lang="prolog"> is_error_type( error, Z30005 ) </syntaxhighlight> Lass uns das Schritt für Schritt tun: # Um einen Test hinzuzufügen, klicke auf der Funktionsseite in der Tabelle "Tests" auf die Schaltfläche "+". Die Felder "Aufruf" und "Ergebnisprüfung" enthalten bereits vordefinierte Funktionen. Um die Fehler zu testen, müssen wir diese jedoch ändern. # Als Erstes richten wir den Aufruf ein: ## Klicke unter "Aufruf" auf die Schaltfläche "›", um den Funktionsaufruf zu erweitern. ## Bearbeite das Feld unter "Funktion" und suche die Funktion "erhalte zweites Element eines typisierten Paars" und wähle sie aus ## Klicke anschließend neben "typisiertes Paar" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "Fehler erhalten, ausgelöst durch Funktionsaufruf" und wähle sie aus ## Klicke neben "Funktionsaufruf" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "verbinde zwei Zeichenketten mit Leerzeichen" (oder nach ZID <code>Z30000</code>) und wähle sie aus ## Lege nun die Eingaben so fest, dass ein Fehler auftritt: Mindestens eine von ihnen muss leer sein. ## Du kannst jetzt deinen "Aufruf" durch erneutes Klicken auf den Pfeil nach unten wieder ausblenden, wenn du möchtest! # Als Nächstes richten wir die Ergebnisprüfung ein: ## Klicke unter "Ergebnisprüfung" auf die Schaltfläche "›", um den Funktionsaufruf zu erweitern. ## Bearbeite das Feld unter "Funktion" und suche die Funktion "ist Fehlertyp" und wähle sie aus ## Du wirst nun nur noch aufgefordert, das zweite Argument zu konfigurieren. Suche unter "Fehlertyp" nach deinem Fehlertyp <code>Z30005</code> und wähle ihn aus. # Und du bist fertig! Du kannst jetzt auf den kreisförmigen Pfeil im Feld "Implementierungen" klicken und solltest grüne Häkchen sehen. Wenn alles geklappt hat, kannst du deinen Test jetzt speichern. Er sollte folgendermaßen aussehen: [[File:Get error expanded.png|frame|center|alt=Testen eines Fehlers mit den Funktionen Fehler erhalten und ist Fehlertyp in ihrer erweiterten Ansicht|Testen eines Fehlers mit den Funktionen Fehler erhalten und ist Fehlertyp in ihrer erweiterten Ansicht]] [[File:Get error collapsed.png|frame|center|alt=Testen eines Fehlers mit den Funktionen Fehler erhalten und ist Fehlertyp in ihrer reduzierten Ansicht|Testen eines Fehlers mit den Funktionen Fehler erhalten und ist Fehlertyp in ihrer reduzierten Ansicht]] <span id="Creating_actionable_error_messages"></span> === Erstellung handlungsorientierter Fehlermeldungen === Wie oben beschrieben, verfügen Fehlertypen über einen optionalen Schlüssel <code>Z50K3</code>, der eine mehrsprachige Liste von HTML-Zeichenketten enthält. Bei der Darstellung von Informationen zu einem Fehler können die im Fehlertyp hinterlegten Meldungen dazu beitragen, eine klare, präzise, ​​informative, übersetzbare und handlungsorientierte Fehlermeldung zu erstellen. Zu diesem Zweck können Fehlermeldungen Parameter wie <code>$1</code>, <code>$2</code> etc. enthalten, wobei die Ziffer dem Argument des Fehlertyps und dessen Wert in der Fehlerinstanz entspricht. Diese Fehlermeldungen werden in Wikifunctions nach der Ausführung eines Funktionsaufrufs im Dialogfenster "Details" angezeigt. Darüber hinaus werden diese Fehlermeldungen auch in anderen Client-Schnittstellen, wie der Abstrakten Wikipedia, ausgegeben, um den Autoren von Abstrakten Inhalten eine bessere Orientierung zu bieten. [[File:Wikifunctions actionable error message example in the Details dialog.png|thumb|Die Fehlermeldung wird unter Verwendung der HTML-Meldung des Fehlertyps und der Werte der Fehlerargumente generiert.]] [[File:Wikifunctions actionable error message example in Abstract Wikipedia.png|thumb|Sofern verfügbar, wird die HTML-Fehlermeldung im Vorschau-Bereich der Abstrakten Wikipedia angezeigt.]] <div lang="en" dir="ltr" class="mw-content-ltr"> Let's use a real example to understand the benefits of HTML error messages: </div> <div lang="en" dir="ltr" class="mw-content-ltr"> The function {{Z|Z37847}} returns the first Lexeme reference given a Wikidata Item reference and a language. When there is no Lexeme for this Item-Language combination, it throws an error of type {{Z|Z28248}}, which has three keys: </div> * <span lang="en" dir="ltr" class="mw-content-ltr">'''Z28248K1''' is the input Wikidata item QID</span> * <span lang="en" dir="ltr" class="mw-content-ltr">'''Z28248K2''' is the connecting property, in this case <code>P5137/item for this sense</code></span> * <span lang="en" dir="ltr" class="mw-content-ltr">'''Z28248K3''' is the language code</span> <div lang="en" dir="ltr" class="mw-content-ltr"> When calling this function for a Wikidata lexeme that doesn't exist, the call will throw an error instance like this: </div> <syntaxhighlight lang="json" highlight="10,12"> { "Z1K1": "Z5", "Z5K1": "Z28248", "Z5K2": { "Z1K1": { "Z1K1": "Z7", "Z7K1": "Z885", "Z885K1": "Z28248" }, "Z28248K1": "Q319", "Z28248K2": "P5137", "Z28248K3": "ast" } } </syntaxhighlight> <div lang="en" dir="ltr" class="mw-content-ltr"> While the error type label indicates: <code>No matching lexeme for item in language</code>, a better error message should indicate: </div> * <span lang="en" dir="ltr" class="mw-content-ltr">which is the failing item,</span> * <span lang="en" dir="ltr" class="mw-content-ltr">which is the language missing, and</span> * <span lang="en" dir="ltr" class="mw-content-ltr">what are the possible ways to fix it.</span> <div lang="en" dir="ltr" class="mw-content-ltr"> The error message <code>Z50K3</code> field can provide this functionality. Whenever an Error Type has an error message for the user language (or any of its fallbacks), the error message shown will be rendered by: </div> # <span lang="en" dir="ltr" class="mw-content-ltr">First, replacing the message parameters with the values of the keys. In our example, any <code>$1</code> will be replaced with the value of <code>Z28248K1</code> ("Q319"), <code>$2</code> with "P5137", and <code>$3</code> with "ast",</span> # <span lang="en" dir="ltr" class="mw-content-ltr">Last, sanitizing and rendering the HTML message.</span> <div lang="en" dir="ltr" class="mw-content-ltr"> So a HTML message like: </div> <syntaxhighlight lang="html"> There is no matching lexeme for the item $1 in "$3".<br> <a href="http://wikidata.org/wiki/$1">Edit in Wikidata</a> </syntaxhighlight> <div lang="en" dir="ltr" class="mw-content-ltr"> Will become: </div> : There is no matching lexeme for the item Q319 in "ast" : [[d:Q319|Edit in Wikidata]] <span id="Debugging_your_implementations"></span> == Debuggen deiner Implementierungen == Manchmal läuft etwas schief. Eine Funktion verhält sich möglicherweise anders als erwartet oder ein Wert erscheint merkwürdig. Implementierungen können mitunter sehr komplex sein, und da sie in einer Spielwiesen-Umgebung ausgeführt werden, kann die Fehlersuche extrem schwierig erscheinen. Um das Verständnis der Vorgänge innerhalb eines Funktionsaufrufs zu erleichtern, bietet Wikifunctions einige Debugging-Werkzeuge. Diese Werkzeuge verändern nicht das Ergebnis einer Funktion, sondern fügen den zurückgegebenen Metadaten zusätzliche Informationen hinzu, die du nach dem Ausführen der Funktion einsehen kannst. Du kannst <code>Wikifunctions.Debug()</code> in deinen Code-Implementierungen oder die Funktion {{Z|Z854}} in deinen Kompositionen verwenden. In diesem Abschnitt erfährst du: * Wie man Debug-Meldungen sowohl aus Code- als auch aus Kompositions-Implementierungen hinzufügt, * Wie man die Metadaten manuell oder über die Benutzeroberfläche untersucht, um diese Protokolle einzusehen. <span id="Debugging_your_code_implementations"></span> === Debuggen deiner Code-Implementierungen === Beim Schreiben von Code, sowohl in JavaScript als auch in Python3, kannst du <code>Wikifunctions.Debug()</code> verwenden, um eine Meldung zu deinem Debug-Protokoll hinzuzufügen und die Ausführung fortzusetzen. {{phab|T441028}} <code>Wikifunctions.Debug()</code> hat einen Parameter, der üblicherweise als Zeichenkette erwartet wird. Jedes andere als Parameter übergebene Objekt wird jedoch direkt in eine Zeichenkette umgewandelt. Um zu unseren Code-Implementierungen für unsere Beispielfunktion "verbinde zwei Zeichenketten mit Leerzeichen" Debug-Protokolle hinzuzufügen, können wir dies in JavaScript tun: <syntaxhighlight lang="JavaScript"> function Z30000( Z30000K1, Z30000K2 ) { if ( trim( Z30000K1 ) === '' ) { Wikifunctions.Debug( `first input is empty "${ Z30000K1 }"` ); Wikifunctions.Error( 'Z30005', [ "Z30000K1", Z30000K1 ] ) } if ( trim( Z30000K2 ) === '' ) { Wikifunctions.Debug( `second input is empty "${ Z30000K2 }"` ); Wikifunctions.Error( 'Z30005', [ "Z30000K2", Z30000K2 ] ) } Wikifunctions.Debug( "both inputs are fine" ); return Z30000K1 + " " + Z30000K2; } </syntaxhighlight> Und das Gleiche in deiner Python3-Implementierung: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): if Z30000K1.strip() == "": Wikifunctions.Debug( 'first input is empty "'+Z30000K1+'"' ) Wikifunctions.Error("Z30005", ["Z30000K1", Z30000K1]) if Z30000K2.strip() == "": Wikifunctions.Debug( 'second input is empty "'+Z30000K2+'"' ) Wikifunctions.Error("Z30005", ["Z30000K2", Z30000K2]) Wikifunctions.Debug( 'both inputs are fine' ) return Z30000K1 + " " + Z30000K2 </syntaxhighlight> Auf diese Weise fügen wir deinen Debug-Protokollen in jedem Fall eine Meldung hinzu: * Schlägt der Funktionsaufruf bei der Überprüfung der ersten oder zweiten Eingabe fehl, ist das Ergebnis der Ausführung ein Fehler, enthält aber einen informativen Protokolleintrag darüber, welcher Zweig den Fehler verursacht hat. * Wenn der Funktionsaufruf erfolgreich ist — weil beide Eingaben gültig sind — gibt der Funktionsaufruf die verbundene Zeichenkette zurück, aber die zurückgegebenen Metadaten enthalten auch ein Debug-Protokoll. <span id="Debugging_your_compositions"></span> === Debuggen deiner Kompositionen === Zur Unterstützung des Debuggens von Kompositionen stellt Wikifunctions die integrierte Funktion {{Z|Z854}} bereit. Mit dieser Funktion kannst du Debug-Meldungen an die Ausführung jedes Funktionsaufrufs anhängen, der die endgültige Ausgabe erzeugt. Die während der Auswertung gesammelten Debug-Protokolle werden als Teil der Ausführungsmetadaten unter dem Schlüssel <code>executorDebugLogs</code> zurückgegeben. <span id="Add_debug_log_to_function_call_(Z854)"></span> ==== Debug-Protokoll zu Funktionsaufruf hinzufügen (Z854) ==== Die Funktion {{Z|Z854}} ist eine integrierte Funktion mit der ZID <code>Z854</code> und benötigt zwei Argumente: * '''Funktionsaufruf''' – Jede Komposition, die du ausführen möchtest. * '''Debug-Protokoll''' – Eine Zeichenketten-Meldung, die protokolliert wird, wenn der angegebene Funktionsaufruf ausgewertet wird. Wenn der umschlossene Funktionsaufruf ausgeführt wird, wird die bereitgestellte Meldung zu den Ausführungsprotokollen hinzugefügt. Wird dieser Funktionsaufruf nicht ausgeführt oder ist seine Ausführung nicht Teil der endgültigen Ausgabe, erscheint sein Debug-Protokoll nicht in den Metadaten des Endergebnisses. Diese integrierte Funktion ist besonders nützlich, wenn du beobachten möchtest: * Welcher Zweig einer Bedingung ausgeführt wurde, oder * Die Reihenfolge der Auswertung in einer Komposition. <span id="Using_Add_debug_log_to_function_call"></span> ==== Verwendung von Debug-Protokoll zu Funktionsaufruf hinzufügen ==== Angenommen, du möchtest zu unserer Beispielfunktion "verbinde zwei Zeichenketten mit Leerzeichen" oder <code>Z30000</code> Debug-Protokolle hinzufügen, sodass für die verschiedenen möglichen Ergebnisse unterschiedliche Meldungen angezeigt werden. Du könntest unsere integrierte Debugging-Funktion wie folgt verwenden: <syntaxhighlight lang="prolog"> if ( is_empty_string( Z30000K1 ), add_debug_log( throw_error( Z30005, ... ), 'failed on first input' ) if( is_empty_string( Z30000K2 ), add_debug_log( throw_error( Z30005, ... ), 'failed on second input' ), add_debug_log( join_with_separator( Z30000K1, Z30000K2, " " ), 'both inputs are ok!' ) ) ) </syntaxhighlight> Dies bewirkt Folgendes: * Wird die Funktion mit einer leeren ersten Eingabe aufgerufen, gibt sie eine Fehlermeldung zurück und die Metadaten enthalten einen Eintrag <code>executorDebugLogs</code> mit dem Protokoll-Eintrag "Fehler bei erster Eingabe". * Wird der Aufruf mit einer leeren zweiten Eingabe aufgerufen, schlägt der Aufruf ebenfalls fehl, die protokollierte Meldung lautet jedoch "Fehler bei zweiter Eingabe". * Bei Aufruf mit gültigen Eingaben gibt die Funktion eine erfolgreiche Antwort zurück und zusätzlich enthalten die Metadaten im Schlüssel <code>executorDebugLogs</code> "Beide Eingaben sind in Ordnung". So würde diese Komposition aussehen: [[File:Add debug log expanded.png|frame|center|alt=Implementierung der Komposition mit Debug-Protokoll hinzufügen, um alle möglichen Ausführungspfade zu protokollieren|Implementierung der Komposition mit Debug-Protokoll hinzufügen, um alle möglichen Ausführungspfade zu protokollieren]] <span id="Accessing_execution_debug_logs"></span> === Zugriff auf Ausführungs-Debug-Protokolle === Unabhängig davon, ob deine Ausführungsprotokolle über <code>Wikifunctions.Debug()</code> oder die integrierte Funktion {{Z|Z854}} hinzugefügt werden, werden sie als Teil der Antwort-Metadaten zurückgegeben. Um die Protokolle zu sehen, klicke nach dem Ausführen deiner Funktion auf die Schaltfläche "Details", die unten im Abschnitt "Ergebnis" erscheint. Die Fehler- und Debug-Informationen werden oben im Dialogfeld "Details" angezeigt. Dies ist das Ergebnis, das du sehen würdest, wenn du die Komposition aus unserem vorherigen Beispiel mit gültigen und ungültigen Eingaben ausführst: {| class="wikitable" | [[File:Execution logs success.png|frameless|center|alt=Funktions-Metadatendialog für eine erfolgreiche Ausführung mit Debug-Protokollen]] | [[File:Execution logs failure.png|frameless|center|alt=Funktions-Metadatendialog für eine fehlgeschlagene Ausführung mit Debug-Protokollen]] |- | Funktions-Metadatendialog für eine erfolgreiche Ausführung: zeigt keine Fehler an, sondern das Protokoll der erfolgreichen Ausführung: ''"Beide Eingaben sind in Ordnung!"'' | Funktions-Metadatendialog für eine fehlgeschlagene Ausführung: zeigt die Fehlerinformationen und das zusätzliche Ausführungsprotokoll für den ersten Fehlerzweig an: ''"Fehler bei erster Eingabe"'' |} [[Category:How to create implementations| {{#translation:}}]] 7a17gnjl58j7j33d5st1yooknkt3558 333946 333944 2026-10-27T19:29:17Z Ameisenigel 44 Created page with "Lass uns anhand eines konkreten Beispiels die Vorteile von HTML-Fehlermeldungen nachvollziehen:" 333946 wikitext text/x-wiki <languages/> Diese Seite bietet eine detailliertere Anleitung dafür, wie man '''Implementierungen erstellt''' und geht über den Überblick auf {{ll|Wikifunctions:Introduction}} hinaus. <span id="Types_of_Implementations"></span> == Arten von Implementierungen == In Wikifunctions kann eine '''Implementierung''' zwei Hauptformen annehmen: '''Code''' oder '''Komposition'''. Eine Code-Implementierung drückt die Logik der Funktion direkt in einer der verfügbaren Programmiersprachen aus (derzeit Python3 oder JavaScript). Sie ist besonders nützlich, wenn sich das Verhalten der Funktion nicht ohne Weiteres aus bestehenden Wikifunktionen ableiten lässt oder wenn eine präzise Kontrolle über die Datenverarbeitung erforderlich ist. Eine Kompositions-Implementierung definiert die Funktion hingegen vollständig durch die Kombination bestehender Funktionen, ohne dass Code geschrieben werden muss. Kompositionen sind leichter verständlich, wiederverwendbar und lassen sich automatisch in andere Sprachen übersetzen. Sie setzen jedoch voraus, dass geeignete Bausteine ​​bereits vorhanden sind und sind oft weniger leistungsfähig. Prüfe daher zunächst, ob dein Ziel durch Komposition erreicht werden kann. Ist dies nicht möglich oder spielen Leistung oder feingranulare Logik eine Rolle, wähle stattdessen eine Code-Implementierung. Es gibt eine dritte Implementierungsart: '''integrierte Implementierungen'''. Diese werden vom Systemcode ausgeführt und können nicht bearbeitet werden. Höchstwahrscheinlich verfügen alle vordefinierten Funktionen über eine integrierte Implementierung. In solchen Fällen wird beim Öffnen der Implementierungsseite die Meldung ''"{{int|wikilambda-implementation-selector-none}}"'' angezeigt. <span id="Practice_Test-Driven_Development"></span> == Praxis der testgetriebenen Entwicklung == '''Testgetriebene Entwicklung''' oder '''TDD''' ist eine Methode zur Softwareentwicklung, bei der Tests geschrieben werden, bevor der eigentliche Code geschrieben wird. Tests dienen dazu, die Funktionsweise einer Funktion anhand von Beispielen und deren Funktionsweise zu verstehen. In Wikifunctions bietet das Schreiben von Tests als erste Tätigkeit erhebliche Vorteile. Wenn du an einer Implementierung arbeitest, kannst du deinen Code anhand der vorhandenen Tests ausführen, um sicherzustellen, dass er sich wie erwartet verhält. Dadurch lassen sich Fehler frühzeitig erkennen, noch bevor du deine Implementierung veröffentlichst. Tests sind außerdem ein effektives Mittel, um die benötigte Funktion zu beschreiben. Durch das Schreiben von Tests '''kommunizierst du klar das erwartete Verhalten''' und die Community kann bei der Implementierung helfen oder alternative Implementierungen erstellen. Stell dir vor, du möchtest eine Funktion implementieren, die zwei Zeichenketten mit einem Leerzeichen dazwischen verknüpft. Ein einfacher Test dafür könnte so aussehen: <syntaxhighlight lang="prolog"> join_with_space( "Hello", "world" ) => "Hello world" </syntaxhighlight> Sobald du das grundlegende Verhalten definiert hast, ist es wichtig, auch '''an Randfälle zu denken''' — Situationen, in denen die Eingaben so beschaffen sind, dass ein spezielles Verhalten erforderlich sein könnte. Was passiert beispielsweise, wenn deine erste Zeichenkette mit einem Leerzeichen endet oder deine zweite mit einem Leerzeichen beginnt? Soll die Funktion alle vorhandenen Leerzeichen beibehalten und ein weiteres hinzufügen oder ein sauber formatiertes Ergebnis mit nur einem Leerzeichen zwischen den Wörtern zurückgeben? Je nach deinen Anforderungen solltest du einen Test für einen solchen Fall erstellen. Ein Test für diesen Sonderfall könnte beispielsweise einer der folgenden sein — aber nicht beide!: <syntaxhighlight lang="prolog"> join_with_space( "Hello ", " world") => "Hello world" </syntaxhighlight> oder ... <syntaxhighlight lang="prolog"> join_with_space( "Hello ", " world") => "Hello world" </syntaxhighlight> Stell sicher, dass deine Tests alle möglichen Sonderfälle abdecken, und sobald du diese hast, stell sicher, dass sie alle mit der Funktion verbunden sind, indem du sie auswählst und auf "Verbinden" klickst. <span id="Code_implementations"></span> == Code-Implementierungen == [[File:Code implementation.png|thumb|alt=Wikifunctions-Code-Editor, der mit einer Funktionsvorlage initialisiert wurde|Beim Hinzufügen einer neuen Code-Implementierung wird die Funktionsvorlage mit den Funktions- und Argumentnamen initialisiert]] Beim Erstellen einer Implementierung mit Code richtet die Wikifunctions-Benutzeroberfläche einen Code-Editor ein, in dem die ausgewählte Sprache für Syntaxhervorhebung und -validierung aktiviert ist. Sobald die zu implementierende Funktion und die Programmiersprache ausgewählt sind, wird dieser Editor mit der korrekten Funktionsvorlage konfiguriert: '''Entferne oder bearbeite sie nicht!''' Platziere deinen Code innerhalb dieser Funktionssignatur. Falls du Hilfsfunktionen benötigst, kannst du diese einfach in deiner Hauptfunktionsdeklaration deklarieren. <span id="Using_input_types_in_your_code"></span> === Verwendung von Eingabetypen in deinem Code === Die Wikifunctions-Typen {{Z|Z6}} und {{Z|Z40}} können in JavaScript und Python3 wie native Typen verwendet werden. Beispielsweise lässt sich eine Zeichenkette verketten oder ein boolescher Wert direkt in einem logischen Ausdruck verwenden. Um andere Typen in deinen Code-Implementierungen zu verwenden, musst du den jeweiligen Typ genauer untersuchen, herausfinden, ob eine Umwandlung in ein natives Äquivalent existiert, und ihn entsprechend behandeln. Nehmen wir beispielsweise an, wir möchten Python-Code schreiben, der eine Eingabe vom Typ {{Z|Z20420}} verarbeitet. Auf der Seite für diesen Typ sehen wir uns die "Typumwandler in Code" an und suchen nach einem Python-Umwandler. Der Umwandler {{Z|Z20424}} wird auf unsere Datumseingabe angewendet, bevor unser Code ausgeführt wird. Unter "nativer Typ" sehen wir, dass unsere Eingabe ein Python-Dictionary ist, und in der Implementierung können wir die zu erwartenden Schlüssel sehen: <syntaxhighlight lang="python3"> return { 'K1': year, 'K2': month, 'K3': day } </syntaxhighlight> Wenn ein Typ keinen Umwandler besitzt, musst du direkt über seine Schlüssel auf seine Bestandteile zugreifen. Nehmen wir beispielsweise an, deine Funktion <code>Z30000</code> hat einen Eingabeparameter <code>Z30000K1</code> vom Typ {{Z|Z11}}. Dieser Typ besitzt zwei Schlüssel: <code>Z11K1</code> für die Sprache (selbst ein Objekt vom Typ {{Z|Z60}}) und <code>Z11K2</code> für den Zeichenketten-Wert. Das Sprachobjekt hat wiederum einen Schlüssel <code>Z60K1</code> für den Sprachcode. Um also eine Zeichenkette mit dem Sprachcode und dem Text zu erhalten, kannst du folgendes schreiben: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1 ) { // z. B. "de: beliebiger Text" return Z30000K1.Z11K1.Z60K1 + ": " + Z30000K1.Z11K2; } </syntaxhighlight> Für eine Kurzübersicht der verfügbaren Typumwandlungen besuche [[Special:MyLanguage/Wikifunctions:Execution targets#Default type conversion|die Tabelle der Standard-Typumwandlungen]]. <span id="Returning_the_right_outputs"></span> === Rückgabe der richtigen Ausgaben === Ähnlich wie bei der Behandlung von Eingaben müssen auch Ausgaben dem in der Funktionsdefinition angegebenen Typ entsprechen. Einige können wie native Typen behandelt werden; daher wird jede Zeichenketten-Ausgabe in ein Wikifunctions-Objekt {{Z|Z6}} und jeder von deiner Implementierung zurückgegebene native boolesche Wert in ein Wikifunctions-Objekt {{Z|Z40}} umgewandelt. Typen mit "Typumwandlern aus Code" wenden die entsprechende Funktion auf die Ausgabe an, um den benötigten Typ zu erzeugen. Am Beispiel von {{Z|Z20420}} transformiert {{Z|Z20443}} die Ausgabe deiner Implementierung – ein Dictionary mit den Schlüsseln K1, K2 und K3 – in die korrekte ZObjekt-Darstellung. Für Typen, die keine Umwandler aus Code haben, kannst du die Ausgabeobjekte sorgfältig erstellen und zurückgeben. Stell dir beispielsweise vor, unsere Funktion <code>Z30000</code> nimmt zwei Zeichenketten als Eingaben entgegen: Sprachcode und Text, und soll ein Objekt {{Z|Z11}} zurückgeben. In Python kannst du dies mit dem Konstruktor <code>ZObject</code> erreichen: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): lang_object = ZObject( {"Z1K1": "Z9", "Z9K1": "Z60"}, Z60K1 = Z30000K1 ) return ZObject( {"Z1K1": "Z9", "Z9K1": "Z11"}, Z11K1 = lang_object, Z11K2 = Z30000K2 ) </syntaxhighlight> Oder in JavaScript: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1, Z30000K2 ) { const langObject = new ZObject( new Map( [ [ "Z60K1", Z30000K1 ] ] ), { "Z1K1": "Z9", "Z9K1": "Z60" } ); const monolingualKeys = new Map( [ [ "Z11K1", langObject ], [ "Z11K2", Z30000K2 ] ] ); return new ZObject( monolingualKeys, { "Z1K1": "Z9", "Z9K1": "Z11" } ); } </syntaxhighlight> Du kannst mehr über die Klasse <code>ZObject</code> und andere nützliche Konstruktoren auf {{ll|Wikifunctions:Execution_targets#Custom_and_non-built-in_type_conversion}} erfahren. {{phab|T392750}}Stand Mai 2026 kann der Versuch, eine Liste von Listen zurückzugeben, fehlschlagen; daher ist es nicht möglich, solche Funktionen in Code zu implementieren. === Code in Python === In diesem Abschnitt geben wir ein konkretes Beispiel, wie man eine Implementierung in Form von Code in Python erstellt. Angenommen, wir möchten eine Implementierung für eine Funktion erstellen, die zwei Eingabezeichenketten durch Einfügen eines Leerzeichens dazwischen kombiniert und das Ergebnis zurückgibt. Nehmen wir an, die ZID dieser Funktion ist Z30000. Die Implementierung wird über die ZID der Funktion definiert. Das gilt auch für die Argumente der Funktion. Im Fall der Funktion Z30000 mit ihren beiden Argumenten sollte die Funktionsvorlage also so aussehen: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): </syntaxhighlight> Wie bereits erwähnt, wissen wir, dass die Argumente (<code>Z30000K1</code> und <code>Z30000K2</code>) Zeichenketten sind, daher können wir sie genauso behandeln wie native Zeichenketten in Python. Die Funktion sollte außerdem eine Zeichenkette zurückgeben. In unserem Beispiel geben wir einfach die beiden Argumente, getrennt durch ein Leerzeichen, aneinandergereiht zurück: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): return Z30000K1 + " " + Z30000K2 </syntaxhighlight> Da es sich um Python handelt, vergesse nicht, diese Zeile einzurücken. Wenn du unserem Rat gefolgt bist, [[#Practice Test-Driven Development|TDD anzuwenden]], verfügst du bereits über eine Reihe von Tests, von denen du weißt, dass sie funktionieren sollten. In diesem Fall kannst du während der Entwicklung deiner Implementierung auf den kreisförmigen Pfeil im Testbereich klicken und überprüfen, ob deine Implementierung alle Tests besteht. Denke daran, dass die Laufzeit keinen Status hat. Gehe nicht von Werten für globale oder statische Variablen aus. Wenn du weitere Fragen dazu hast, was du in Python tun kannst und was nicht, frage auf [[Wikifunctions:Python implementations]]. === Code in JavaScript === In diesem Abschnitt geben wir ein konkretes Beispiel, wie man eine Implementierung in Form von Code in JavaScript erstellt. Angenommen, wir möchten eine Implementierung für eine Funktion erstellen, die zwei Eingabezeichenketten durch Einfügen eines Leerzeichens dazwischen kombiniert und das Ergebnis zurückgibt. Nehmen wir an, die ZID dieser Funktion ist <code>Z30000</code>. Die Implementierung wird über die ZID der Funktion definiert. Das gilt auch für die Argumente der Funktion. Im Fall der Funktion <code>Z30000</code> mit ihren beiden Argumenten sollte die Funktionsvorlage also so aussehen: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1, Z30000K2 ) { } </syntaxhighlight> Wir wissen, dass die Argumente (<code>Z30000K1</code> und <code>Z30000K2</code>) Zeichenketten sind, daher können wir sie in JavaScript wie native Zeichenketten behandeln. Die Funktion soll außerdem eine Zeichenkette zurückgeben. Um die Funktion zu vervollständigen, kannst du eine Zeile hinzufügen, die die Eingabezeichenketten verkettet, etwa so: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1, Z30000K2 ) { return Z30000K1 + " " + Z30000K2; } </syntaxhighlight> Wenn du Tests wie im Abschnitt [[#Practice Test-Driven Development|TDD]] oben empfohlen hast, klicke auf den kreisförmigen Pfeil im Testbereich und prüfe, ob deine Implementierung alle Tests besteht. Denke daran, dass die Laufzeit keinen Status hat. Gehe nicht von Werten für globale oder statische Variablen aus. Wenn du weitere Fragen dazu hast, was du in JavaScript tun kannst und was nicht, frage auf [[Wikifunctions:JavaScript implementations]]. <span id="Calling_another_Wikifunctions_function"></span> === Aufruf einer anderen Wikifunctions-Funktion === Eine Code-Implementierung kann bestimmte andere Wikifunctions-Funktionen aufrufen, die Ausgabe des Aufrufs empfangen und diese Ausgabe für die weitere Verarbeitung nutzen. Wir bezeichnen solche Aufrufe als Callbacks. Derzeit können aus Sicherheits- und Leistungsgründen nur die folgenden integrierten Wikidata-Abruf- und Suchfunktionen auf diese Weise aufgerufen werden: {{Z|Z6820}}, {{Z|Z6821}}, {{Z|Z6822}}, {{Z|Z6824}}, {{Z|Z6825}}, {{Z|Z6826}}, {{Z|Z6830}} und {{Z|Z6831}}. Diese Funktionalität befindet sich in einem frühen Stadium der Einführung; wir hoffen, in Zukunft Aufrufe für eine größere Bandbreite an Funktionen zu ermöglichen. Betrachten wir eine JavaScript-Implementierung, die einen Callback enthält. Diese Implementierung ruft ein Datenobjekt von Wikidata ab, extrahiert die Bezeichnung dieses Datenobjektes in einer bestimmten Sprache und gibt die Bezeichnung als Zeichenkette zurück. Das abzurufende Datenobjekt wird über das Argument <code>Z400K1</code> angegeben, die Sprache über <code>Z400K2</code>. <syntaxhighlight lang="javascript"> function Z400( Z400K1, Z400K2 ) { const item = Wikifunctions.Call('Z6821', Z400K1); for (const label of item.Z6001K2.Z12K1) { if (label.Z11K1.Z60K1 === Z400K2.Z60K1) { return label.Z11K2; }} return 'NOT FOUND'; } </syntaxhighlight> Ein Callback wird durch den Aufruf von <code>Wikifunctions.Call</code> ausgelöst, wie im Beispiel gezeigt. Das erste Argument für <code>Wikifunctions.Call</code> ist stets die ZID der aufzurufenden Funktion – in diesem Fall {{Z|Z6821}}, welche ein einzelnes Argument entgegennimmt. Darauf folgen, durch Kommas getrennt, die an diese Funktion zu übergebenden Argumente. Hierbei handelt es sich bei dem Argument <code>Z400K1</code> um denselben Wert, der auch an <code>Z400</code> übergeben wurde. Dies ist ein gängiges Muster für die Argumentübergabe an Callbacks, jedoch können die Argumente auch mit dem Konstruktor <code>ZObject</code> (wie oben beschrieben) erstellt oder auf andere Weise bezogen werden. Der Wert von <code>Z400K1</code> wäre eine Instanz von {{Z|Z6091}}, die die QID des abzurufenden Datenobjekts enthält. Zeile 2 des Beispiels ruft <code>Z6821</code> auf, um dieses Datenobjekt von Wikidata abzurufen, und weist das resultierende ZObjekt der Konstante <code>item</code> zu. Der restliche Code durchläuft die Bezeichnungen des Datenobjekts, bis er diejenige findet, die der durch <code>Z400K2</code> angegebenen Sprache entspricht. Für das obige Beispiel haben wir der Einfachheit halber <code>Z6821</code> verwendet. Sofern die Implementierung jedoch nicht das gesamte Objekt benötigt, wird dringend empfohlen, zum Abrufen von Wikidata-Datenobjekten, die sehr groß sein können, <code>Z6820</code> zu verwenden. Obwohl der Aufruf von <code>Z6820</code> etwas komplexer ist, ermöglichen seine Parameter das Abrufen spezifischer Teile eines Wikidata-Datenobjekts. Dies kann die Leistung erheblich steigern und bestimmte Fehler vermeiden, da weniger Netzwerkbandbreite und Verarbeitungszeit erforderlich sind. (<code>Z6820</code> kann auch statt <code>Z6822</code>, <code>Z6824</code>, <code>Z6825</code> und <code>Z6826</code> verwendet werden, um ähnliche Vorteile bei der Bandweitenreduzierung zu erreichen.) Im Folgenden zeigen wir, wie <code>Z6820</code> in <code>Wikifunctions.Call</code> verwendet werden kann, um dasselbe Verhalten wie oben zu erzielen. Beachte, dass wir das zweite an <code>Z6820</code> übergebene Argument, <code>[labelsPart]</code>, nutzen, um festzulegen: “Gib nur die Bezeichnungen des Datenobjekts zurück”, und das dritte Argument, <code>[Z400K2]</code>, verwenden, um festzulegen: “Gib die Bezeichnungen nur in der angegebenen Sprache zurück”. (Dieses Argument würde auch für Aliasse und Beschreibungen gelten, sofern diese im Ergebnis enthalten wären.) <syntaxhighlight lang="javascript"> function Z400( Z400K1, Z400K2 ) { const labelsPart = new ZObject( new Map( [ ['Z6030K1', new ZReference('Z6033')] ] ), {Z1K1: 'Z9', Z9K1: 'Z6030'} ); const entities = Wikifunctions.Call( 'Z6820', [Z400K1], [labelsPart], [Z400K2], []); const item = entities.get(Z400K1.Z6091K1); const labels = item.Z6001K2.Z12K1; for (const label of labels) { if (label.Z11K1.Z60K1 === Z400K2.Z60K1) { return label.Z11K2; }} return 'NOT FOUND'; } </syntaxhighlight> Weitere zu beachtende Hinweise: * Obwohl Code-Implementierungen mittlerweile in der Lage sind, Wikidata-Entitäten abzurufen, wird empfohlen, dass sie keine ''vollständigen'' Entitäten zurückgeben. Dies liegt an den derzeitigen Beschränkungen hinsichtlich der Größe des von einer Code-Implementierung zurückgegebenen Wertes. Um eine vollständige, große Entität abzurufen und zurückzugeben, ist es besser, die Abruffunktion aus einer Komposition heraus aufzurufen. * Es kann nur ein Callback gleichzeitig ausgeführt werden. Aus Sicherheitsgründen ist es nicht möglich, die Nebenläufigkeitsfunktionen von JavaScript oder Python zu nutzen, um mehrere Callbacks parallel auszuführen. ** Beachte jedoch, dass du mithilfe von Z6820 mehrere Entitäten auf einmal abrufen kannst. * Derzeit gibt es eine Obergrenze von 3 MiB für die Größe von Wikidata-Inhalten, die über einen einzelnen Callback an eine Code-Implementierung zurückgegeben werden können. Dieselbe Obergrenze gilt für die Größe des Ergebnisses, das von einer Code-Implementierung zurückgegeben wird. <span id="Compositions"></span> == Kompositionen == Im diesem Abschnitt geben wir ein konkretes Beispiel, wie man eine Implementierung in Form einer Komposition erstellt. Angenommen, wir möchten eine Implementierung für eine Funktion erstellen, die zwei Eingabezeichenketten durch Einfügen eines Leerzeichens dazwischen kombiniert und das Ergebnis zurückgibt. Nehmen wir an, die ZID dieser Funktion ist <code>Z30000</code>. Normalerweise ist es sinnvoll, zunächst darüber nachzudenken, wie man vorhandene Funktionen kombinieren kann, um die gewünschte Ausgabe zu erzielen. Manchmal mag dies trivial sein und du kannst einfach mit dem Zusammenstellen und Funktionen fortfahren, aber in vielen Fällen lohnt es sich, die gewünschte Komposition zu notieren. Beispielsweise könnten wir für die angegebene Funktion die vorhandene Funktion {{Z|Z10000}} verwenden. Diese Funktion nimmt zwei Zeichenketten und erstellt daraus eine Zeichenkette. Aber wir müssen dazwischen ein Leerzeichen einfügen. Wir verbinden also zunächst ein Leerzeichen mit dem Ende der ersten Zeichenkette und verbinden dann die zweite Zeichenfolge mit dem Ergebnis dieser ersten Verbindung. Unsere Komposition könnte also so notiert werden: <syntaxhighlight lang="prolog"> join_strings( join_strings( Z30000K1, " " ), Z30000K2 ) </syntaxhighlight> Es gibt mehrere Möglichkeiten, eine Komposition zu schreiben: Beachte, dass dasselbe auch auf folgende Weise erreicht werden kann: <syntaxhighlight lang="prolog"> join_strings( Z30000K1, join_strings( " ", Z30000K2 ) ) </syntaxhighlight> Eine alternative Implementierung könnte auch die vorhandene Funktion {{Z|Z15175}} verwenden, sodass deine Komposition wie folgt aussehen könnte: <syntaxhighlight lang="prolog"> join_with_separator( Z30000K1, Z30000K2, " " ) </syntaxhighlight> Wie du siehst, gibt es mehrere Möglichkeiten, dies zu erreichen. Nimm dir also Zeit und erkunde die vorhandenen Funktionen, die im {{ll|Wikifunctions:Catalogue}} verfügbar sind. Versuchen wir, das zweite Beispiel zu erstellen, <code>join_strings(Z30000K1, join_strings(" ", Z30000K2))</code>. Um dies zu erstellen: # Um eine Implementierung hinzuzufügen, klicke auf der Funktionsseite in der Tabelle "Implementierungen" auf die Schaltfläche "+". # Stelle sicher, dass die Option "Komposition" unter "Implementierung" ausgewählt ist. # Klicke auf das Symbol "›" oder auf den Link "Funktion auswählen", um die Funktionsdetails anzuzeigen. # Suche unter "Funktion" nach dem Namen der äußersten Funktion, die du verwenden möchtest, in diesem Beispiel "verbinde Zeichenketten". Wähle anschließend die gewünschte Funktion aus der Dropdown-Liste aus. # Du siehst zwei neue Felder, eines für jedes der Argumente, die für die ausgewählte Funktion benötigt werden. # Als erstes Argument möchten wir den ersten Eingabewert für unsere Funktion auswählen: ## Klicke neben "erste Zeichenkette" auf die Schaltfläche "…" und wähle "Argumentreferenz" aus. ## Unter "Schlüssel-ID" kannst du nun die erste Zeichenkette deiner Funktion aus dem Dropdown-Menü auswählen, das alle verfügbaren Eingaben enthält. # Für das zweite Argument möchten wir das Ergebnis eines weiteren Aufrufs von "verbinde Zeichenketten" verwenden: ## Klicke neben "zweite Zeichenkette" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus. ## Suche unter "Funktion" nach der Funktion, die du aufrufen möchtest und wähle sie aus, nämlich "verbinde Zeichenketten". ## Konfiguriere die "erste Zeichenkette" für diesen inneren Funktionsaufruf, indem du einfach ein Leerzeichen in das Textfeld eingibst, und konfiguriere die "zweite Zeichenkette" wie in Schritt 6: Ändere sie mit der Schaltfläche "…" in "Argumentreferenz" und wähle dann das zweite Argument in der Dropdown-Liste aus. Deine Komposition ist nun fertig! Du kannst die Details mithilfe der Pfeiltasten ein- und ausblenden, um dir einen Überblick zu verschaffen. Falls du bereits Tests wie im Abschnitt [[#Practice Test-Driven Development|TDD]] oben empfohlen implementiert hast, klicke im Testbereich auf den kreisförmigen Pfeil und prüfe, ob deine Implementierung die Tests besteht. Sobald deine Komposition die Tests bestanden hat, kannst du sie veröffentlichen. [[File:Composition implementation expanded.png|frame|center|alt=Eine Wikifunctions-Kompositionsimplementierung in ihrer erweiterten Ansicht|Eine Wikifunctions-Kompositionsimplementierung in ihrer erweiterten Ansicht]] [[File:Composition implementation collapsed.png|frame|center|alt=Eine Wikifunctions-Kompositionsimplementierung in ihrer reduzierten Ansicht|Eine Wikifunctions-Kompositionsimplementierung in ihrer reduzierten Ansicht]] <span id="Wikifunctions_error_handling"></span> == Fehlerbehandlung auf Wikifunctions == Als Ersteller einer Wikifunctions-Funktion möchtest du möglicherweise den Benutzer warnen, der deine Funktion aufruft, wenn im Code ein Fehler auftritt oder seine Eingaben bestimmte Kriterien nicht erfüllen. Wenn deine Funktion beispielsweise eine Zeichenkette mit einem Namen erwartet, solltest du prüfen, ob der Name nicht leer ist, und gegebenenfalls eine verständliche Fehlermeldung anzeigen. Hierfür kannst du <code>Wikifunctions.Error()</code> in deinen Code-Implementierungen oder die Funktion {{Z|Z851}} in deinen Kompositionen verwenden. In diesem Abschnitt erfährst du: * Wie man Fehler sowohl aus Code- als auch aus Kompositions-Implementierungen auslöst, * wie man Tests für Fehlerfälle schreibt, und * wie man Fehler abfängt und behandelt, die von Funktionen ausgelöst werden, die man in seinen Kompositionen verwendet. <span id="Throwing_errors_from_code_implementations"></span> === Fehler aus Code-Implementierungen auslösen === Sowohl beim Schreiben von JavaScript- als auch von Python-Code kannst du <code>Wikifunctions.Error()</code> nutzen, um die Ausführung mit einem gewünschten Fehler zu beenden. <code>Wikifunctions.Error()</code> hat zwei Parameter: # Fehlertyp: Eine Zeichenkette, die die ZID des Fehlertyps enthält, den du zurückgeben möchtest. # Fehlerargumente: Eine Liste von Zeichenkettenargumenten zur Erstellung des Fehlers. Gehen wir sie der Reihe nach durch: <span id="Error_type"></span> ==== Fehlertyp ==== Ein Fehlertyp ist ein Objekt, das eine Art von Fehler beschreibt, der im System auftreten kann. Es gibt eine Reihe vordefinierter Fehlertypen, du kannst aber auch eigene Fehlertypen erstellen, die besser zu deinem Anwendungsfall passen. Bei der Verwendung von Fehlern empfiehlt es sich, die verfügbaren Fehlertypen zu durchsuchen, die sich in [[Special:ListObjectsByType/Z50|dieser Liste]] finden. Falls keine passenden Fehler für deinen Fall vorhanden sind, erstelle einen neuen Fehler, indem du zur Erstellungsseite gehst und im Typauswahlfeld "Fehlertyp" auswählst. Lege anschließend die erforderlichen Felder fest: [[File:Error type.png|thumb|alt=Erstellung von Fehlertypen in Wikifunctions|Um einen neuen Fehlertyp (Z50) zu erstellen, bearbeite die Bezeichnung und füge die erforderlichen Schlüssel hinzu.]] * '''Bezeichnung''' – Dies ist der Haupttitel des Fehlers, der eine kurze, aber aussagekräftige Meldung enthalten sollte. Lege die Fehlerbezeichnung im rechten Feld mit dem Titel "Info" fest. * '''Schlüssel''' – Schlüssel enthalten zusätzliche Informationen zur Fehlerursache. Wenn beispielsweise eine Eingabe das falsche Format aufwies, möchtest du den Benutzer möglicherweise über den eingegebenen Inhalt informieren, wenn der Fehler auftritt. Um sie in deinen Implementierungen zu verwenden, müssen Schlüssel vom Zeichenketten sein. Um einen Schlüssel zu erstellen, klicke auf das Symbol "[+]" unterhalb von "Schlüssel", wähle unter "Werttyp" die Option "Zeichenkette" aus und füge eine aussagekräftige Bezeichnung hinzu, beispielsweise "tatsächlich Eingabe". Sobald du alle erforderlichen Schlüssel erstellt hast, kannst du deinen Fehlertyp veröffentlichen und die ID des neu erstellten Objekts speichern. * '''Fehlermeldung''' – Fehlertypen können ein mehrsprachiges Array von Fehlermeldungen enthalten, die mit HTML-Parametern versehen sind. Die Parameter werden als $1, $2 etc. angegeben, wobei die Ziffer dem Schlüssel des Fehlertyps entspricht. Beim Erstellen eines Fehlertyps mit dem Zeichenketten-Schlüssel "aktuelle Eingabe", kann die Fehlermeldung beispielsweise den Platzhalter "$1" verwenden, der zum Zeitpunkt der Fehlerausgabe durch den Wert des Schlüssels "aktuelle Eingabe" ersetzt wird. Um HTML-Meldungen hinzuzufügen, klicke unter "HTML-Fragmente" auf das Symbol "[+]", wähle eine Sprache aus und gib die HTML-Zeichenkette ein. <span id="Error_arguments"></span> ==== Fehlerargumente ==== Fehlerargumente entsprechen den Schlüsseln des Fehlertyps und sollten zusätzliche Informationen zum Verständnis des Fehlers liefern. Fehlerargumente sollten immer Zeichenketten sein. <span id="Using_Wikifunctions.Error()"></span> ==== Verwendung von Wikifunctions.Error() ==== Angenommen, du möchtest einen Fehler auslösen, wenn entweder deine erste oder deine zweite Eingabe leer ist. Du hast den Fehlertyp bereits erstellt und ihm wurde die ZID <code>Z30005</code> zugewiesen. Dein Fehlertyp hat zwei Zeichenketten-Schlüssel: * Eingabeschlüssel: Enthält den Schlüssel der fehlerhaften Eingabe * Eingabewert: Enthält den aktuellen Wert der fehlerhaften Eingabe Um einen Fehler in deiner JavaScript-Implementierung auszulösen, solltest du etwa Folgendes tun: <syntaxhighlight lang="javascript"> function Z30000( Z30000K1, Z30000K2 ) { if ( trim( Z30000K1 ) === '' ) { // Wenn die erste Eingabe leer ist, löse Fehler Z30005 aus // mit zwei Zeichenketten-Argumenten: [ erster Eingabe-Schlüssel, erster Eingabe-Wert ] Wikifunctions.Error( 'Z30005', [ "Z30000K1", Z30000K1 ] ) } if ( trim( Z30000K2 ) === '' ) { // Wenn die zweite Eingabe leer ist, löse Fehler Z30005 aus // mit zwei Zeichenketten-Argumenten: [ zweiter Eingabe-Schlüssel, zweiter Eingabe-Wert ] Wikifunctions.Error( 'Z30005', [ "Z30000K2", Z30000K2 ] ) } return Z30000K1 + " " + Z30000K2; } </syntaxhighlight> Um einen Fehler in deiner Python-Implementierung auszulösen, solltest du etwa Folgendes tun: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): if Z30000K1.strip() == "": # Wenn die erste Eingabe leer ist, löse Fehler Z30005 aus # mit zwei Zeichenketten-Argumenten: [ erster Eingabe-Schlüssel, erster Eingabe-Wert ] Wikifunctions.Error("Z30005", ["Z30000K1", Z30000K1]) if Z30000K2.strip() == "": # Wenn die zweite Eingabe leer ist, löse Fehler Z30005 aus # mit zwei Zeichenketten-Argumenten: [ erster Eingabe-Schlüssel, erster Eingabe-Wert ] Wikifunctions.Error("Z30005", ["Z30000K2", Z30000K2]) return Z30000K1 + " " + Z30000K2 </syntaxhighlight> Denke daran, dass der Aufruf von <code>Wikifunctions.Error()</code> die Ausführung beendet! <span id="Throwing_errors_from_compositions"></span> === Fehler aus Kompositionen auslösen === Wenn du eine Kompositionsimplementierung erstellst, kannst du einen Fehler auslösen, indem du die Spezialfunktion {{Z|Z851}} aufrufst. <span id="Throw_Error_function_(Z851)"></span> ==== Funktion Fehler auslösen (Z851) ==== Die Funktion {{Z|Z851}} ähnelt der Methode <code>Wikifunctions.Error()</code> und benötigt zwei Argumente: * '''Fehlertyp''' – Ein Verweis auf den Fehlertyp, den du auslösen möchtest * '''Fehlerparameter''' – Eine Liste mit den Argumenten zur Erstellung deines Fehlers, die ebenfalls Zeichenketten sein sollten. <span id="Using_Throw_Error"></span> ==== Verwendung von Fehler auslösen ==== Angenommen, du möchtest deine Komposition so ändern, dass sie zuerst prüft, ob die Argumente nicht leer sind, und einen Fehler ausgibt, wenn sie ein leeres Argument findet. Wenn dann keines der Argumente leer ist, wird die ursprüngliche Komposition ausgeführt, die wie folgt aussieht: <syntaxhighlight lang="prolog"> join_with_separator( Z30000K1, Z30000K2, " " ) </syntaxhighlight> Dazu musst du bedingte Pfade erstellen, für die du die Funktion {{Z|Z802}} verwenden kannst. Stell es dir folgendermaßen vor: * Wenn das erste Argument leer ist, soll ein Fehler für das erste Argument ausgelöst werden * Andernfalls wird mit der Überprüfung des zweiten Arguments fortgefahren * Wenn das zweite Argument leer ist, soll ein Fehler für das zweite Argument ausgelöst werden * Andernfalls wird der Erfolgspfad verfolgt und die verbundenen Zeichenketten mit dem Leerzeichen als Trennzeichen zurückgegeben Oder in funktionalem Pseudocode: <syntaxhighlight lang="prolog"> if ( is_empty_string( Z30000K1 ), throw_error( Z30005, [ "Z30000K1", Z30000K1 ] ), if( is_empty_string( Z30000K2 ), throw_error( Z30005, [ "Z30000K2", Z30000K2 ] ), join_with_separator( Z30000K1, Z30000K2, " " ) ) ) </syntaxhighlight> Lass uns das Schritt für Schritt erstellen: # Um eine Implementierung hinzuzufügen, klicke auf der Funktionsseite in der Tabelle "Implementierungen" auf die Schaltfläche "+". # Stelle sicher, dass die Option "Komposition" unter "Implementierung" ausgewählt ist. # Klicke auf das Symbol "›" oder auf den Link "Funktion auswählen", um die Funktionsdetails anzuzeigen. # Suche unter "Funktion" nach der äußersten Funktion, die du verwenden möchtest, in diesem Fall "wenn", und wähle sie aus. # Überprüfe die Gültigkeit des ersten Arguments: ## Klicke neben "Bedingung" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "ist leere Zeichenkette" und wähle sie aus ## Klicke neben "Eingabe" auf die Schaltfläche "…" und wähle "Argumentreferenz" aus ## Wähle unter "Schlüssel-ID" die erste Eingabe aus (z. B. "erste Zeichenkette") ## Du kannst den Funktionsaufruf der "Bedingung" nun bei Bedarf ausblenden, indem du auf den Pfeil nach unten neben "Bedingung" klickst. Es sollte dann etwa Folgendes angezeigt werden: "f(x) ist leere Zeichenkette ( → erste Zeichenkette )" # Fehler auslösen, wenn die Bedingung wahr ist: ## Klicke neben "dann" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "Fehler auslösen" und wähle sie aus ## Suche unter "Fehlertyp" nach deinem Fehlertyp (du kannst die Fehler-ID direkt eingeben, wenn du sie kennst, z. B. Z30005) und wähle ihn aus ## Füge unter "Fehlerparameter" zwei Elemente hinzu, indem du auf die Schaltfläche "+" klickst ## Lege für "Objekt 1" (fehlerhafter Argumentschlüssel) den Typ auf "Zeichenkette" fest und trage die Argumentkennung ein (z. B. "erste Eingabe" oder "Z30000K1") ## Klicke für "Objekt 2" (fehlerhafter Argumentwert) auf die "…" neben "Objekt 2" und wähle "Argumentreferenz" aus ## Wähle unter "Schlüssel-ID" die erste Eingabe aus (z. B. "erste Zeichenkette") ## Du kannst den Funktionsaufruf "dann" nun bei Bedarf ausblenden, indem du auf den Pfeil nach unten neben "dann" klickst. Es sollte dann etwa Folgendes angezeigt werden: "f(x) Fehler auslösen ( ungültiges Format, typisierte Liste ( Objekt, "erste Eingabe", → erste Zeichenkette ) )" # Prüfe das zweite Argument, wenn das erste korrekt war: ## Klicke neben "sonst" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "wenn" und wähle sie aus ## Richte eine "Bedingung" ein, um die Gültigkeit des zweiten Arguments zu überprüfen, indem du das gleiche Verfahren wie in Schritt 5 beschrieben anwendest. ## Richte "dann" so ein, dass beim zweiten Argument ein Fehler ausgelöst wird, indem du das gleiche Verfahren wie in Schritt 6 beschrieben anwendest. # Richte schließlich den Erfolgspfad ein: ## Klicke neben dem verschachtelten "sonst" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der gewünschten Funktion, in diesem Fall "vereinige zwei Zeichenketten mit Trennzeichen", und wähle sie aus ## Klicke neben "erste Zeichenkette" auf die Schaltfläche "…" und setze sie auf "Argumentreferenz", wähle anschließend "erste Zeichenkette" aus ## Klicke neben "zweite Zeichenkette" auf die Schaltfläche "…" und setze sie auf "Argumentreferenz", wähle anschließend "zweite Zeichenkette" aus ## Füge unter "Trennzeichen" ein Leerzeichen in das Textfeld ein Der resultierende Funktionsaufruf sollte folgendermaßen aussehen: [[File:Throw error expanded.png|frame|center|alt=Wikifunctions-Komposition mit der Funktion Fehler auslösen|Wikifunctions-Komposition mit der Funktion Fehler auslösen]] [[File:Throw error collapsed.png|frame|center|alt=Wikifunctions-Komposition mit der Funktion Fehler auslösen in ihrer reduzierten Ansicht|Wikifunctions-Komposition mit der Funktion Fehler auslösen in ihrer reduzierten Ansicht]] <span id="Handling_errors_in_compositions"></span> === Fehlerbehandlung in Kompositionen === Es ist zwar nützlich, Funktionen das Auslösen erwarteter Fehler zu ermöglichen, aber es ist entscheidend, Fehler in den eigenen Kompositionen behandeln zu können, um diese Funktionen sicher verwenden zu können. Angenommen, du möchtest eine neue Funktion "vollständiger Name einer Person" erstellen – wir bezeichnen sie mit der ZID <code>Z30010</code>. Diese Funktion soll den vollständigen Namen einer Person anhand ihres Vor- und Nachnamens zurückgeben. Ist jedoch eines der beiden Felder leer, soll sie stattdessen den Text "Unbekannt" zurückgeben. Du könntest eine Komposition erstellen, indem du unsere Beispielfunktion "verbinde zwei Zeichenketten mit Leerzeichen" oder <code>Z30000</code> verwendest, um den Namen zu generieren. Wenn eine der Eingaben leer ist, weißt du, dass <code>Z30000</code> einen Fehler vom Typ <code>Z30005</code> auslöst. Mithilfe der Funktion {{Z|Z850}} als Wrapper kannst du die Verbindungsoperation ausführen und einen möglichen Fehler abfangen, indem du einfach "Unbekannt" zurückgibst, wenn er auftritt. <span id="Try-Catch_function_(Z850)"></span> ==== Try-Catch-Funktion (Z850) ==== Die Funktion {{Z|Z850}} ist eine integrierte Funktion mit der ZID <code>Z850</code> und benötigt drei Argumente: * '''Funktionsaufruf''' – Der erste Funktionsaufruf, der ausgeführt werden soll. Wenn kein Fehler auftritt, ist die Antwort das Ergebnis dieses Funktionsaufrufs. * '''Fehlertyp''' – Ein Fehlertyp, der abgefangen werden soll, falls er während der Ausführung des ersten Funktionsaufrufs auftritt. * '''Fehlerhandler''' – Ein Funktionsaufruf, der ausgeführt wird, falls der oben genannte Fehler während der Ausführung des ursprünglichen Funktionsaufrufs auftritt. In diesem Fall wird das Ergebnis der Fehlerbehandlung zurückgegeben. <span id="Using_Try-Catch"></span> ==== Verwendung der Try-Catch-Funktion ==== Sobald wir alle Funktionen für unsere Komposition haben, können wir sie folgendermaßen gestalten: <syntaxhighlight lang="prolog"> try_catch( join_with_space( Z30010K1, Z30010K2 ), Z30005, echo( "Unknown" ) ) </syntaxhighlight> Das bedeutet: * Die Funktion "verbinde zwei Zeichenketten mit Leerzeichen" wird mit den beiden Eingaben ausprobiert und wenn alles erfolgreich verläuft, wird das Ergebnis dieser Funktion zurückgegeben * Wenn eine der Eingaben leer ist, löst "verbinde zwei Zeichenketten mit Leerzeichen" einen Fehler vom Typ <code>Z30005</code> aus * Unsere {{Z|Z850}} erkennt dann diesen Fehler und führt die Funktion {{Z|Z801}} aus, die "Unbekannt" zurückgibt Lass uns das Schritt für Schritt erstellen: # Um eine Implementierung hinzuzufügen, klicke auf der Funktionsseite in der Tabelle "Implementierungen" auf die Schaltfläche "+". # Stelle sicher, dass die Option "Komposition" unter "Implementierung" ausgewählt ist. # Klicke auf das Symbol "›" oder auf den Link "Funktion auswählen", um die Funktionsdetails anzuzeigen. # Suche unter "Funktion" nach der äußersten Funktion, die du verwenden möchtest, in diesem Fall "Try-Catch-Funktion", und wähle sie aus. # Richte den Hauptfunktionsaufruf ein: ## Klicke unterhalb des Feldes, in dem die "Try-Catch-Funktion" ausgewählt ist, neben dem Schlüssel "Funktionsaufruf" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "verbinde zwei Zeichenketten mit Leerzeichen" und wähle sie aus ## Klicke neben "erste Zeichenkette" auf die Schaltfläche "…" und wähle "Argumentreferenz" aus, wähle anschließend das Argument "erster Name" aus der Dropdown-Liste aus. ## Klicke neben "zweite Zeichenkette" auf die Schaltfläche "…" und wähle "Argumentreferenz" aus, wähle anschließend das Argument "zweiter Name" aus der Dropdown-Liste aus. # Wähle den abzufangenden Fehler aus: ## Suche unter "Fehlertyp" nach "ungültige Zeichenkette" und wähle es aus – du kannst direkt nach der ZID <code>Z30005</code> suchen # Richte den Funktionsaufruf für den Fehlerhandler ein: ## Klicke neben "Fehlerhandler" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "Echo" und wähle sie aus ## Suche unter "Eingabe" und "Typ" den Typ "Zeichenkette" und wähle ihn aus ## Gib nun unter "Eingabe" im Textfeld "Unbekannt" ein Die resultierende Funktion sollte folgendermaßen aussehen: [[File:Try catch expanded.png|frame|center|alt=Wikifunctions-Komposition mit der Try-Catch-Funktion in ihrer erweiterten Ansicht|Wikifunctions-Komposition mit der Try-Catch-Funktion in ihrer erweiterten Ansicht]] [[File:Try catch collapsed.png|frame|center|alt=Wikifunctions-Komposition mit der Try-Catch-Funktion in ihrer reduzierten Ansicht|Wikifunctions-Komposition mit der Try-Catch-Funktion in ihrer reduzierten Ansicht]] <span id="Testing_your_failure_use_cases"></span> === Testen deiner Fehlerfälle === Wie bereits im Abschnitt über die [[#Practice Test-Driven Development|Anwendung von TDD]] erläutert, ist es wichtig, nicht nur die häufigsten Ausführungspfade, sondern auch mögliche Randfälle zu testen. Ebenso wichtig ist es, das Fehlerverhalten zu prüfen. In diesem Abschnitt stellen wir dir die notwendigen Werkzeuge vor, um zu testen, ob deine Funktion bei bestimmten Eingaben fehlschlägt und ob die Fehlermeldung den Erwartungen entspricht. Dazu benötigst du zwei weitere Systemfunktionen: <span id="Is_error_type_(Z852)"></span> ==== ist Fehlertyp (Z852) ==== Die Funktion {{Z|Z852}} ist eine integrierte Funktion mit der ZID <code>Z852</code> und benötigt zwei Argumente: * '''Fehler''' – Ein {{Z|Z5}}-Objekt, das bei einem fehlgeschlagenen Aufruf ausgelöst werden kann. Eine Fehlerinstanz hat einen Typ und einen Wert. * '''Fehlertyp''' – Ein Verweis auf einen {{Z|Z50}}, der mit dem als erstes Argument übergebenen Fehlertyp verglichen wird. Ist dies der Fall, gibt die Funktion wahr zurück. <span id="Get_error_thrown_by_function_call_(Z853)"></span> ==== Fehler erhalten, ausgelöst durch Funktionsaufruf (Z853) ==== Die Funktion {{Z|Z853}} ist eine integrierte Funktion mit der ZID <code>Z853</code> und benötigt ein Argument: * '''Funktionsaufruf''' – Ein Funktionsaufruf, der entweder einen erfolgreichen Wert beliebigen Typs zurückgibt oder einen Fehler auslöst. Diese Funktion gibt ein {{Z|Z882}} zurück, wobei an erster Stelle ein {{Z|Z40}} und an zweiter Stelle ein {{Z|Z1}} steht: * Wenn der Funktionsaufruf erfolgreich ist und somit keinen Fehler auslöst, enthält das zurückgegebene Paar an erster Stelle falsch und an zweiter Stelle leer. * Wenn der Funktionsaufruf einen Fehler auslöst, enthält das zurückgegebene Paar an erster Stelle wahr und an zweiter Stelle den abgefangenen Fehler. Um diese Funktion in deinen Kompositionen zu verwenden, musst du möglicherweise die zusätzlichen Funktionen verwenden: * {{Z|Z821}} und * {{Z|Z822}} <span id="Testing_errors"></span> ==== Fehler testen ==== Angenommen, unsere Zielfunktion "verbinde zwei Zeichenketten mit Leerzeichen" oder <code>Z30000</code> löst einen Fehler vom Typ <code>Z30005</code> aus, und wir möchten dieses Verhalten testen. Dazu müssen wir Folgendes tun: * Einen fehlgeschlagenen Funktionsaufruf auslösen * Den Fehler mit der Funktion {{Z|Z853}} erhalten * Mit {{Z|Z852}} prüfen, ob der Fehler den richtigen Typ hat Tests haben zwei Felder: * '''Aufruf''' – Ein Funktionsaufruf, der mit den zu testenden Eingaben eine Ausgabe erzeugt. Dieser Aufruf gibt einen Wert zurück. * '''Ergebnisprüfung''' – Ein Funktionsaufruf, der überprüft, ob der vom vorherigen Aufruf zurückgegebene Wert dem erwarteten Wert entspricht. Das erste Argument dieses Funktionsaufrufs wird automatisch mit dem Rückgabewert des ersten Aufrufs belegt. Für eine Schritt-für-Schritt-Anleitung zum Erstellen von Tests siehe {{ll|Wikifunctions:Introduction#Create_tests}}. In unserem Beispiel können wir es so strukturieren — aber das ist nicht die einzige Möglichkeit! Der Aufruf, der ein {{Z|Z5}}-Objekt zurückgibt: <syntaxhighlight lang="prolog"> error = get_second_element_of_typed_list( get_error_thrown_by( join_strings_by_whitespace( "", "not empty" ) ) ) </syntaxhighlight> Und die Ergebnisprüfung, die das {{Z|Z5}}-Objekt als erstes Argument verwendet: <syntaxhighlight lang="prolog"> is_error_type( error, Z30005 ) </syntaxhighlight> Lass uns das Schritt für Schritt tun: # Um einen Test hinzuzufügen, klicke auf der Funktionsseite in der Tabelle "Tests" auf die Schaltfläche "+". Die Felder "Aufruf" und "Ergebnisprüfung" enthalten bereits vordefinierte Funktionen. Um die Fehler zu testen, müssen wir diese jedoch ändern. # Als Erstes richten wir den Aufruf ein: ## Klicke unter "Aufruf" auf die Schaltfläche "›", um den Funktionsaufruf zu erweitern. ## Bearbeite das Feld unter "Funktion" und suche die Funktion "erhalte zweites Element eines typisierten Paars" und wähle sie aus ## Klicke anschließend neben "typisiertes Paar" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "Fehler erhalten, ausgelöst durch Funktionsaufruf" und wähle sie aus ## Klicke neben "Funktionsaufruf" auf die Schaltfläche "…" und wähle "Funktionsaufruf" aus ## Suche unter "Funktion" nach der Funktion "verbinde zwei Zeichenketten mit Leerzeichen" (oder nach ZID <code>Z30000</code>) und wähle sie aus ## Lege nun die Eingaben so fest, dass ein Fehler auftritt: Mindestens eine von ihnen muss leer sein. ## Du kannst jetzt deinen "Aufruf" durch erneutes Klicken auf den Pfeil nach unten wieder ausblenden, wenn du möchtest! # Als Nächstes richten wir die Ergebnisprüfung ein: ## Klicke unter "Ergebnisprüfung" auf die Schaltfläche "›", um den Funktionsaufruf zu erweitern. ## Bearbeite das Feld unter "Funktion" und suche die Funktion "ist Fehlertyp" und wähle sie aus ## Du wirst nun nur noch aufgefordert, das zweite Argument zu konfigurieren. Suche unter "Fehlertyp" nach deinem Fehlertyp <code>Z30005</code> und wähle ihn aus. # Und du bist fertig! Du kannst jetzt auf den kreisförmigen Pfeil im Feld "Implementierungen" klicken und solltest grüne Häkchen sehen. Wenn alles geklappt hat, kannst du deinen Test jetzt speichern. Er sollte folgendermaßen aussehen: [[File:Get error expanded.png|frame|center|alt=Testen eines Fehlers mit den Funktionen Fehler erhalten und ist Fehlertyp in ihrer erweiterten Ansicht|Testen eines Fehlers mit den Funktionen Fehler erhalten und ist Fehlertyp in ihrer erweiterten Ansicht]] [[File:Get error collapsed.png|frame|center|alt=Testen eines Fehlers mit den Funktionen Fehler erhalten und ist Fehlertyp in ihrer reduzierten Ansicht|Testen eines Fehlers mit den Funktionen Fehler erhalten und ist Fehlertyp in ihrer reduzierten Ansicht]] <span id="Creating_actionable_error_messages"></span> === Erstellung handlungsorientierter Fehlermeldungen === Wie oben beschrieben, verfügen Fehlertypen über einen optionalen Schlüssel <code>Z50K3</code>, der eine mehrsprachige Liste von HTML-Zeichenketten enthält. Bei der Darstellung von Informationen zu einem Fehler können die im Fehlertyp hinterlegten Meldungen dazu beitragen, eine klare, präzise, ​​informative, übersetzbare und handlungsorientierte Fehlermeldung zu erstellen. Zu diesem Zweck können Fehlermeldungen Parameter wie <code>$1</code>, <code>$2</code> etc. enthalten, wobei die Ziffer dem Argument des Fehlertyps und dessen Wert in der Fehlerinstanz entspricht. Diese Fehlermeldungen werden in Wikifunctions nach der Ausführung eines Funktionsaufrufs im Dialogfenster "Details" angezeigt. Darüber hinaus werden diese Fehlermeldungen auch in anderen Client-Schnittstellen, wie der Abstrakten Wikipedia, ausgegeben, um den Autoren von Abstrakten Inhalten eine bessere Orientierung zu bieten. [[File:Wikifunctions actionable error message example in the Details dialog.png|thumb|Die Fehlermeldung wird unter Verwendung der HTML-Meldung des Fehlertyps und der Werte der Fehlerargumente generiert.]] [[File:Wikifunctions actionable error message example in Abstract Wikipedia.png|thumb|Sofern verfügbar, wird die HTML-Fehlermeldung im Vorschau-Bereich der Abstrakten Wikipedia angezeigt.]] Lass uns anhand eines konkreten Beispiels die Vorteile von HTML-Fehlermeldungen nachvollziehen: <div lang="en" dir="ltr" class="mw-content-ltr"> The function {{Z|Z37847}} returns the first Lexeme reference given a Wikidata Item reference and a language. When there is no Lexeme for this Item-Language combination, it throws an error of type {{Z|Z28248}}, which has three keys: </div> * <span lang="en" dir="ltr" class="mw-content-ltr">'''Z28248K1''' is the input Wikidata item QID</span> * <span lang="en" dir="ltr" class="mw-content-ltr">'''Z28248K2''' is the connecting property, in this case <code>P5137/item for this sense</code></span> * <span lang="en" dir="ltr" class="mw-content-ltr">'''Z28248K3''' is the language code</span> <div lang="en" dir="ltr" class="mw-content-ltr"> When calling this function for a Wikidata lexeme that doesn't exist, the call will throw an error instance like this: </div> <syntaxhighlight lang="json" highlight="10,12"> { "Z1K1": "Z5", "Z5K1": "Z28248", "Z5K2": { "Z1K1": { "Z1K1": "Z7", "Z7K1": "Z885", "Z885K1": "Z28248" }, "Z28248K1": "Q319", "Z28248K2": "P5137", "Z28248K3": "ast" } } </syntaxhighlight> <div lang="en" dir="ltr" class="mw-content-ltr"> While the error type label indicates: <code>No matching lexeme for item in language</code>, a better error message should indicate: </div> * <span lang="en" dir="ltr" class="mw-content-ltr">which is the failing item,</span> * <span lang="en" dir="ltr" class="mw-content-ltr">which is the language missing, and</span> * <span lang="en" dir="ltr" class="mw-content-ltr">what are the possible ways to fix it.</span> <div lang="en" dir="ltr" class="mw-content-ltr"> The error message <code>Z50K3</code> field can provide this functionality. Whenever an Error Type has an error message for the user language (or any of its fallbacks), the error message shown will be rendered by: </div> # <span lang="en" dir="ltr" class="mw-content-ltr">First, replacing the message parameters with the values of the keys. In our example, any <code>$1</code> will be replaced with the value of <code>Z28248K1</code> ("Q319"), <code>$2</code> with "P5137", and <code>$3</code> with "ast",</span> # <span lang="en" dir="ltr" class="mw-content-ltr">Last, sanitizing and rendering the HTML message.</span> <div lang="en" dir="ltr" class="mw-content-ltr"> So a HTML message like: </div> <syntaxhighlight lang="html"> There is no matching lexeme for the item $1 in "$3".<br> <a href="http://wikidata.org/wiki/$1">Edit in Wikidata</a> </syntaxhighlight> <div lang="en" dir="ltr" class="mw-content-ltr"> Will become: </div> : There is no matching lexeme for the item Q319 in "ast" : [[d:Q319|Edit in Wikidata]] <span id="Debugging_your_implementations"></span> == Debuggen deiner Implementierungen == Manchmal läuft etwas schief. Eine Funktion verhält sich möglicherweise anders als erwartet oder ein Wert erscheint merkwürdig. Implementierungen können mitunter sehr komplex sein, und da sie in einer Spielwiesen-Umgebung ausgeführt werden, kann die Fehlersuche extrem schwierig erscheinen. Um das Verständnis der Vorgänge innerhalb eines Funktionsaufrufs zu erleichtern, bietet Wikifunctions einige Debugging-Werkzeuge. Diese Werkzeuge verändern nicht das Ergebnis einer Funktion, sondern fügen den zurückgegebenen Metadaten zusätzliche Informationen hinzu, die du nach dem Ausführen der Funktion einsehen kannst. Du kannst <code>Wikifunctions.Debug()</code> in deinen Code-Implementierungen oder die Funktion {{Z|Z854}} in deinen Kompositionen verwenden. In diesem Abschnitt erfährst du: * Wie man Debug-Meldungen sowohl aus Code- als auch aus Kompositions-Implementierungen hinzufügt, * Wie man die Metadaten manuell oder über die Benutzeroberfläche untersucht, um diese Protokolle einzusehen. <span id="Debugging_your_code_implementations"></span> === Debuggen deiner Code-Implementierungen === Beim Schreiben von Code, sowohl in JavaScript als auch in Python3, kannst du <code>Wikifunctions.Debug()</code> verwenden, um eine Meldung zu deinem Debug-Protokoll hinzuzufügen und die Ausführung fortzusetzen. {{phab|T441028}} <code>Wikifunctions.Debug()</code> hat einen Parameter, der üblicherweise als Zeichenkette erwartet wird. Jedes andere als Parameter übergebene Objekt wird jedoch direkt in eine Zeichenkette umgewandelt. Um zu unseren Code-Implementierungen für unsere Beispielfunktion "verbinde zwei Zeichenketten mit Leerzeichen" Debug-Protokolle hinzuzufügen, können wir dies in JavaScript tun: <syntaxhighlight lang="JavaScript"> function Z30000( Z30000K1, Z30000K2 ) { if ( trim( Z30000K1 ) === '' ) { Wikifunctions.Debug( `first input is empty "${ Z30000K1 }"` ); Wikifunctions.Error( 'Z30005', [ "Z30000K1", Z30000K1 ] ) } if ( trim( Z30000K2 ) === '' ) { Wikifunctions.Debug( `second input is empty "${ Z30000K2 }"` ); Wikifunctions.Error( 'Z30005', [ "Z30000K2", Z30000K2 ] ) } Wikifunctions.Debug( "both inputs are fine" ); return Z30000K1 + " " + Z30000K2; } </syntaxhighlight> Und das Gleiche in deiner Python3-Implementierung: <syntaxhighlight lang="python3"> def Z30000(Z30000K1, Z30000K2): if Z30000K1.strip() == "": Wikifunctions.Debug( 'first input is empty "'+Z30000K1+'"' ) Wikifunctions.Error("Z30005", ["Z30000K1", Z30000K1]) if Z30000K2.strip() == "": Wikifunctions.Debug( 'second input is empty "'+Z30000K2+'"' ) Wikifunctions.Error("Z30005", ["Z30000K2", Z30000K2]) Wikifunctions.Debug( 'both inputs are fine' ) return Z30000K1 + " " + Z30000K2 </syntaxhighlight> Auf diese Weise fügen wir deinen Debug-Protokollen in jedem Fall eine Meldung hinzu: * Schlägt der Funktionsaufruf bei der Überprüfung der ersten oder zweiten Eingabe fehl, ist das Ergebnis der Ausführung ein Fehler, enthält aber einen informativen Protokolleintrag darüber, welcher Zweig den Fehler verursacht hat. * Wenn der Funktionsaufruf erfolgreich ist — weil beide Eingaben gültig sind — gibt der Funktionsaufruf die verbundene Zeichenkette zurück, aber die zurückgegebenen Metadaten enthalten auch ein Debug-Protokoll. <span id="Debugging_your_compositions"></span> === Debuggen deiner Kompositionen === Zur Unterstützung des Debuggens von Kompositionen stellt Wikifunctions die integrierte Funktion {{Z|Z854}} bereit. Mit dieser Funktion kannst du Debug-Meldungen an die Ausführung jedes Funktionsaufrufs anhängen, der die endgültige Ausgabe erzeugt. Die während der Auswertung gesammelten Debug-Protokolle werden als Teil der Ausführungsmetadaten unter dem Schlüssel <code>executorDebugLogs</code> zurückgegeben. <span id="Add_debug_log_to_function_call_(Z854)"></span> ==== Debug-Protokoll zu Funktionsaufruf hinzufügen (Z854) ==== Die Funktion {{Z|Z854}} ist eine integrierte Funktion mit der ZID <code>Z854</code> und benötigt zwei Argumente: * '''Funktionsaufruf''' – Jede Komposition, die du ausführen möchtest. * '''Debug-Protokoll''' – Eine Zeichenketten-Meldung, die protokolliert wird, wenn der angegebene Funktionsaufruf ausgewertet wird. Wenn der umschlossene Funktionsaufruf ausgeführt wird, wird die bereitgestellte Meldung zu den Ausführungsprotokollen hinzugefügt. Wird dieser Funktionsaufruf nicht ausgeführt oder ist seine Ausführung nicht Teil der endgültigen Ausgabe, erscheint sein Debug-Protokoll nicht in den Metadaten des Endergebnisses. Diese integrierte Funktion ist besonders nützlich, wenn du beobachten möchtest: * Welcher Zweig einer Bedingung ausgeführt wurde, oder * Die Reihenfolge der Auswertung in einer Komposition. <span id="Using_Add_debug_log_to_function_call"></span> ==== Verwendung von Debug-Protokoll zu Funktionsaufruf hinzufügen ==== Angenommen, du möchtest zu unserer Beispielfunktion "verbinde zwei Zeichenketten mit Leerzeichen" oder <code>Z30000</code> Debug-Protokolle hinzufügen, sodass für die verschiedenen möglichen Ergebnisse unterschiedliche Meldungen angezeigt werden. Du könntest unsere integrierte Debugging-Funktion wie folgt verwenden: <syntaxhighlight lang="prolog"> if ( is_empty_string( Z30000K1 ), add_debug_log( throw_error( Z30005, ... ), 'failed on first input' ) if( is_empty_string( Z30000K2 ), add_debug_log( throw_error( Z30005, ... ), 'failed on second input' ), add_debug_log( join_with_separator( Z30000K1, Z30000K2, " " ), 'both inputs are ok!' ) ) ) </syntaxhighlight> Dies bewirkt Folgendes: * Wird die Funktion mit einer leeren ersten Eingabe aufgerufen, gibt sie eine Fehlermeldung zurück und die Metadaten enthalten einen Eintrag <code>executorDebugLogs</code> mit dem Protokoll-Eintrag "Fehler bei erster Eingabe". * Wird der Aufruf mit einer leeren zweiten Eingabe aufgerufen, schlägt der Aufruf ebenfalls fehl, die protokollierte Meldung lautet jedoch "Fehler bei zweiter Eingabe". * Bei Aufruf mit gültigen Eingaben gibt die Funktion eine erfolgreiche Antwort zurück und zusätzlich enthalten die Metadaten im Schlüssel <code>executorDebugLogs</code> "Beide Eingaben sind in Ordnung". So würde diese Komposition aussehen: [[File:Add debug log expanded.png|frame|center|alt=Implementierung der Komposition mit Debug-Protokoll hinzufügen, um alle möglichen Ausführungspfade zu protokollieren|Implementierung der Komposition mit Debug-Protokoll hinzufügen, um alle möglichen Ausführungspfade zu protokollieren]] <span id="Accessing_execution_debug_logs"></span> === Zugriff auf Ausführungs-Debug-Protokolle === Unabhängig davon, ob deine Ausführungsprotokolle über <code>Wikifunctions.Debug()</code> oder die integrierte Funktion {{Z|Z854}} hinzugefügt werden, werden sie als Teil der Antwort-Metadaten zurückgegeben. Um die Protokolle zu sehen, klicke nach dem Ausführen deiner Funktion auf die Schaltfläche "Details", die unten im Abschnitt "Ergebnis" erscheint. Die Fehler- und Debug-Informationen werden oben im Dialogfeld "Details" angezeigt. Dies ist das Ergebnis, das du sehen würdest, wenn du die Komposition aus unserem vorherigen Beispiel mit gültigen und ungültigen Eingaben ausführst: {| class="wikitable" | [[File:Execution logs success.png|frameless|center|alt=Funktions-Metadatendialog für eine erfolgreiche Ausführung mit Debug-Protokollen]] | [[File:Execution logs failure.png|frameless|center|alt=Funktions-Metadatendialog für eine fehlgeschlagene Ausführung mit Debug-Protokollen]] |- | Funktions-Metadatendialog für eine erfolgreiche Ausführung: zeigt keine Fehler an, sondern das Protokoll der erfolgreichen Ausführung: ''"Beide Eingaben sind in Ordnung!"'' | Funktions-Metadatendialog für eine fehlgeschlagene Ausführung: zeigt die Fehlerinformationen und das zusätzliche Ausführungsprotokoll für den ersten Fehlerzweig an: ''"Fehler bei erster Eingabe"'' |} [[Category:How to create implementations| {{#translation:}}]] 8wv3f9yrwhkrnrqcb69c54hjwjzulu3 User:SpBot/Archivebot 2 20640 333908 158143 2026-10-27T18:43:52Z SpBot 978 Updating the page 333908 wikitext text/x-wiki {| class="wikitable" style="float:right; box-sizing: border-box; display: flex-root;" !colspan="2"| Archiving bot exists at |- !colspan="2"| [[File:Wikimedia-logo.svg|12px]] Meta: [[meta:User:SpBot|User page]] |- !colspan="2"| [[File:Commons-logo.svg|12px]] Commons: [[:c:User:SpBot|User page]] |- !colspan="2"| [[File:Wikidata-logo-en.svg|12px]] Wikidata: [[d:User:SpBot|User page]] |- !colspan="2"| [[File:Wikimania.svg|12px]] Wikimania: [[:wmania:User:SpBot|User page]] |- !colspan="2"| [[File:Wikispecies-logo.svg|12px]] Wikispecies: [[:species:User:SpBot|User page]] |- !colspan="2"| [[File:Wikifunctions-logo.svg|12px]] Wikifunctions: [[:wikifunctions:User:SpBot|User page]] |- !colspan="2"| [[File:Incubator-logo.svg|12px]] Incubator: [[:incubator:User:SpBot|User page]] |- |'''[[File:Wikipedia-logo.png|20px]] Wikipedia''' || [[:w:cs:User:SpBot|cs]], [[:w:de:User:SpBot|de]], [[:w:it:User:SpBot|it]], [[:w:ja:User:SpBot|ja]], [[:w:ko:User:SpBot|ko]], [[:w:simple:User:SpBot|simple]], [[:w:vi:User:SpBot|vi]] |- |'''[[File:Wikisource-logo.svg|16px]] Wikisource''' || [[:s:de:User:SpBot|de]], [[:s:en:User:SpBot|en]] |- |'''[[File:Wiktionary-ico-de.png|16px]] Wiktionary''' || [[:wikt:de:User:SpBot|de]] |- |'''[[File:Wikiversity-logo-de.svg|16px]] Wikiversity''' || [[:wikiversity:de:User:SpBot|de]] |- |colspan="2"|<small>[[Special:CentralAuth/SpBot|SUL account]] | [[:c:User:SpBot/Archivebot|edit templ]]</small> |} r8zsb16kt1td15d93nxf7oe1cgdsito Z20361 0 43713 333947 140892 2026-10-27T19:35:02Z Ameisenigel 44 de 333947 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z20361" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z20357", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z20357", "Z20357K1": { "Z1K1": "Z20342", "Z20342K1": "Z16112", "Z20342K2": { "Z1K1": "Z13518", "Z13518K1": "31" } }, "Z20357K2": { "Z1K1": "Z40", "Z40K1": "Z41" } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z13522", "Z13522K2": { "Z1K1": "Z13518", "Z13518K1": "366" } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "December 31st is the 366th day in a leap year" }, { "Z1K1": "Z11", "Z11K1": "Z1430", "Z11K2": "31. Dezember ist im Schaltjahr 366. Tag" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } qc9ofzxbw0xhde8598y01ikktyfug8w Z20362 0 43714 333948 236934 2026-10-27T19:36:08Z Ameisenigel 44 de 333948 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z20362" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z16683", "Z17K2": "Z20362K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Day number" }, { "Z1K1": "Z11", "Z11K1": "Z1004", "Z11K2": "numéro du jour" }, { "Z1K1": "Z11", "Z11K1": "Z1787", "Z11K2": "numero del giorno" }, { "Z1K1": "Z11", "Z11K1": "Z1078", "Z11K2": "Hari ke-x" }, { "Z1K1": "Z11", "Z11K1": "Z1430", "Z11K2": "Tageszahl" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z40", "Z17K2": "Z20362K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "leap year?" }, { "Z1K1": "Z11", "Z11K1": "Z1004", "Z11K2": "est-ce une année bissextile ?" }, { "Z1K1": "Z11", "Z11K1": "Z1787", "Z11K2": "anno bisestile?" }, { "Z1K1": "Z11", "Z11K1": "Z1078", "Z11K2": "Apakah tahun kabisat?" }, { "Z1K1": "Z11", "Z11K1": "Z1430", "Z11K2": "Schaltjahr?" } ] } } ], "Z8K2": "Z20342", "Z8K3": [ "Z20", "Z20364", "Z20365", "Z20366", "Z20370", "Z20369" ], "Z8K4": [ "Z14", "Z20363" ], "Z8K5": "Z20362" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": " Day number in year to Day of Roman Year" }, { "Z1K1": "Z11", "Z11K1": "Z1004", "Z11K2": "numéro du jour dans l'année en jour" }, { "Z1K1": "Z11", "Z11K1": "Z1787", "Z11K2": "numero del giorno in Giorno di Anno Romano" }, { "Z1K1": "Z11", "Z11K1": "Z1078", "Z11K2": "Hari ke-x dalam penanggalan Romawi" }, { "Z1K1": "Z11", "Z11K1": "Z1430", "Z11K2": "Tageszahl in Tag des Römischen Jahres" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31", { "Z1K1": "Z31", "Z31K1": "Z1787", "Z31K2": [ "Z6", "n-esimo giorno dell'anno" ] } ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1004", "Z11K2": "renvoie le jour de l'année à partir du numéro de jour dans l'année" }, { "Z1K1": "Z11", "Z11K1": "Z1787", "Z11K2": "Dato il numero del giorno (dal primo dell'anno) calcola il corrispondente giorno del calendario" }, { "Z1K1": "Z11", "Z11K1": "Z1078", "Z11K2": "Mencari tanggal dari hari ke-x di kalender Romawi" } ] } } hmhsscee9n8y6q1j7yzs40rxoqt8og9 Z20363 0 43715 333949 305089 2026-10-27T19:36:34Z Ameisenigel 44 de 333949 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z20363" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z20362", "Z14K3": { "Z1K1": "Z16", "Z16K1": "Z610", "Z16K2": "def Z20362(Z20362K1, Z20362K2):\n\tlength = 365 + int(Z20362K2)\n\tmonthLengths = [31, 28 + int(Z20362K2), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]\n\tnum = Z20362K1\n\tnum = num % length\n\tnum = length if num == 0 else num\n\tmonth = 1\n\tfor i in monthLengths:\n\t\tif num \u003E i:\n\t\t\tmonth += 1\n\t\t\tnum -= i\n\treturn {\n\t\t\"K1\": month,\n\t\t\"K2\": num\n\t}" } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1004", "Z11K2": "numéro du jour dans l'année en jour, en Python" }, { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Day number in year to Day of Roman Year Python" }, { "Z1K1": "Z11", "Z11K1": "Z1430", "Z11K2": "Tageszahl in Tag des Römischen Jahres in Python" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } pqy3go78g5xcc6rpffkzsynswtf6mtc Z20364 0 43716 333950 140931 2026-10-27T19:37:23Z Ameisenigel 44 de 333950 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z20364" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z20362", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z20362", "Z20362K1": { "Z1K1": "Z16683", "Z16683K1": { "Z1K1": "Z16659", "Z16659K1": "Z16660" }, "Z16683K2": { "Z1K1": "Z13518", "Z13518K1": "1" } }, "Z20362K2": { "Z1K1": "Z40", "Z40K1": "Z42" } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z20348", "Z20348K2": { "Z1K1": "Z20342", "Z20342K1": "Z16101", "Z20342K2": { "Z1K1": "Z13518", "Z13518K1": "1" } } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "1 is January 1st" }, { "Z1K1": "Z11", "Z11K1": "Z1430", "Z11K2": "1 ist 1. Januar" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } bvug0zf5549z1r7oowoazgdo9jnvruy Z20365 0 43717 333951 140932 2026-10-27T19:38:22Z Ameisenigel 44 de 333951 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z20365" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z20362", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z20362", "Z20362K1": { "Z1K1": "Z16683", "Z16683K1": "Z16660", "Z16683K2": { "Z1K1": "Z13518", "Z13518K1": "365" } }, "Z20362K2": { "Z1K1": "Z40", "Z40K1": "Z42" } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z20348", "Z20348K2": { "Z1K1": "Z20342", "Z20342K1": "Z16112", "Z20342K2": { "Z1K1": "Z13518", "Z13518K1": "31" } } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "365 in non-leap year is 31 December" }, { "Z1K1": "Z11", "Z11K1": "Z1430", "Z11K2": "365 im Gemeinjahr ist 31. Dezember" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } ms4kazf9mi6jqd4dse0az5zd27bx8n6 Z20366 0 43718 333952 140933 2026-10-27T19:39:04Z Ameisenigel 44 de 333952 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z20366" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z20362", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z20362", "Z20362K1": { "Z1K1": "Z16683", "Z16683K1": "Z16660", "Z16683K2": { "Z1K1": "Z13518", "Z13518K1": "365" } }, "Z20362K2": { "Z1K1": "Z40", "Z40K1": "Z41" } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z20348", "Z20348K2": { "Z1K1": "Z20342", "Z20342K1": "Z16112", "Z20342K2": { "Z1K1": "Z13518", "Z13518K1": "30" } } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "365 in leap year is 30 December" }, { "Z1K1": "Z11", "Z11K1": "Z1430", "Z11K2": "365 im Schaltjahr ist 30. Dezember" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } rsq32o379o7m9tgqz0fa8gutp2ersx0 Z20367 0 43719 333953 148374 2026-10-27T19:42:38Z Ameisenigel 44 de 333953 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z20367" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z20342", "Z17K2": "Z20367K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "day" }, { "Z1K1": "Z11", "Z11K1": "Z1004", "Z11K2": "jour d'origine" }, { "Z1K1": "Z11", "Z11K1": "Z1430", "Z11K2": "Tag" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z16683", "Z17K2": "Z20367K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "move by" }, { "Z1K1": "Z11", "Z11K1": "Z1004", "Z11K2": "déplacer de ... jours" }, { "Z1K1": "Z11", "Z11K1": "Z1430", "Z11K2": "verschieben um" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z40", "Z17K2": "Z20367K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Leap year?" }, { "Z1K1": "Z11", "Z11K1": "Z1004", "Z11K2": "est-ce une année bissextile ?" }, { "Z1K1": "Z11", "Z11K1": "Z1430", "Z11K2": "Schaltjahr?" } ] } } ], "Z8K2": "Z20342", "Z8K3": [ "Z20", "Z20372", "Z20373", "Z20375", "Z20376", "Z20377" ], "Z8K4": [ "Z14", "Z20368" ], "Z8K5": "Z20367" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Move N dates" }, { "Z1K1": "Z11", "Z11K1": "Z1004", "Z11K2": "déplacer les dates de N jours" }, { "Z1K1": "Z11", "Z11K1": "Z1430", "Z11K2": "um N Tage verschieben" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31", { "Z1K1": "Z31", "Z31K1": "Z1002", "Z31K2": [ "Z6", "add N days to day of year", "day of year shifted", "shifted day of year", "subtract days from date", "add days to date", "date shift", "shift date" ] } ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "returns the day of a Roman year shifted by an integer N number of days. May not be correct if it goes outside the year of origin." }, { "Z1K1": "Z11", "Z11K1": "Z1004", "Z11K2": "renvoie le jour d'une année romaine décalé d'un nombre entier N de jours ; cela peut ne pas être correct si l'année d'origine est dépassée" }, { "Z1K1": "Z11", "Z11K1": "Z1430", "Z11K2": "gibt das Datum eines Römischen Jahres aus, das um die angegebene Anzahl von Tagen verschoben wurde" } ] } } i1k6jfi5zfwmw5xhmij6cvf6767zyvi Z20368 0 43720 333954 305072 2026-10-27T19:43:02Z Ameisenigel 44 de 333954 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z20368" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z20367", "Z14K2": { "Z1K1": "Z7", "Z7K1": "Z20362", "Z20362K1": { "Z1K1": "Z7", "Z7K1": "Z16693", "Z16693K1": { "Z1K1": "Z7", "Z7K1": "Z17101", "Z17101K1": { "Z1K1": "Z7", "Z7K1": "Z20357", "Z20357K1": { "Z1K1": "Z18", "Z18K1": "Z20367K1" }, "Z20357K2": { "Z1K1": "Z18", "Z18K1": "Z20367K3" } } }, "Z16693K2": { "Z1K1": "Z18", "Z18K1": "Z20367K2" } }, "Z20362K2": { "Z1K1": "Z18", "Z18K1": "Z20367K3" } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1004", "Z11K2": "déplacer les dates de N jours, en Composition" }, { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Move N dates Composition" }, { "Z1K1": "Z11", "Z11K1": "Z1430", "Z11K2": "um N Tage verschieben als Komposition" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } m6pstq7csznwgqwc75h9bt74z4lf1ox Z20369 0 43721 333955 141012 2026-10-27T19:43:54Z Ameisenigel 44 de 333955 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z20369" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z20362", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z20362", "Z20362K1": { "Z1K1": "Z16683", "Z16683K1": { "Z1K1": "Z16659", "Z16659K1": "Z16662" }, "Z16683K2": { "Z1K1": "Z13518", "Z13518K1": "1" } }, "Z20362K2": { "Z1K1": "Z40", "Z40K1": "Z41" } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z20348", "Z20348K2": { "Z1K1": "Z20342", "Z20342K1": "Z16112", "Z20342K2": { "Z1K1": "Z13518", "Z13518K1": "30" } } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "-1 in a leap year is December 30" }, { "Z1K1": "Z11", "Z11K1": "Z1430", "Z11K2": "-1 im Schaltjahr ist 30. Dezember" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } lxrqgopiiswccnaqgm7ynwjhwk923q5 Z20370 0 43722 333956 140935 2026-10-27T19:44:53Z Ameisenigel 44 de 333956 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z20370" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z20362", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z20362", "Z20362K1": { "Z1K1": "Z16683", "Z16683K1": { "Z1K1": "Z16659", "Z16659K1": "Z16660" }, "Z16683K2": { "Z1K1": "Z13518", "Z13518K1": "367" } }, "Z20362K2": { "Z1K1": "Z40", "Z40K1": "Z41" } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z20348", "Z20348K2": { "Z1K1": "Z20342", "Z20342K1": "Z16101", "Z20342K2": { "Z1K1": "Z13518", "Z13518K1": "1" } } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "367 in a leap year is January 1st" }, { "Z1K1": "Z11", "Z11K1": "Z1430", "Z11K2": "367 im Schaltjahr ist 1. Januar" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } dd5rlf4avg9etlli0l5o1l1t2tgam39 Talk:Z23 1 83589 334021 328022 2026-10-27T23:45:07Z Jdforrester (WMF) 4 /* English label */ Reply 334021 wikitext text/x-wiki {{type documentation|Z23|Nothing |related types= * {{Z+|Z22}} * {{Z+|Z5}} * {{Z+|Z21}} |cardinality=Valid: {{formatnum:0}} <br>Type admits: {{formatnum:1}} |proposal=<!--N/A--> }} == English label == I've just fixed a handful of cases where someone had tried to insert a literal Z23 in a composition, presumably by entering <q>nothing</q> into the Type field. If we swapped out its label for one of its aliases, like <q>Unreachable</q>, that should prevent further mistakes. (It would also free up the term <q>nothing</q> in case [[WT:Naming_conventions#Void_is_meaningless|we want to use that for Z24's label]].) [[User:YoshiRulz|YoshiRulz]] ([[User talk:YoshiRulz|talk]]) 06:27, 26 May 2026 (UTC) :@[[User:YoshiRulz|YoshiRulz]]: This is not "unreachable", though, and it's intentionally distinct from Z24 in the type system. [[User:Jdforrester (WMF)|Jdforrester (WMF)]] ([[User talk:Jdforrester (WMF)|talk]]) 16:59, 1 June 2026 (UTC) :Found and fixed more. I've changed the label to "Never". [[User:YoshiRulz|YoshiRulz]] ([[User talk:YoshiRulz|talk]]) 19:00, 16 October 2026 (UTC) ::I don't think that's semantically correct. [[User:Jdforrester (WMF)|Jdforrester (WMF)]] ([[User talk:Jdforrester (WMF)|talk]]) 23:45, 27 October 2026 (UTC) == Purpose == Why do we need an empty type?<br>In type-theoretic systems, the empty type is necessary to express impossibilities or contradictions. {{SITENAME}} is not a theorem prover.<br>In strongly-typed languages, a subroutine which throws has return type <code>Never</code>. {{SITENAME}} has out-of-band error handling but is dynamically-typed&mdash;the return type of {{Z|851}} is currently {{Z|1}} so that the editor will allow you to use it anywhere, but it wouldn't really matter if it were {{Z|23}} or {{Z|21}} since ''no value is ever returned''. [[User:YoshiRulz|YoshiRulz]] ([[User talk:YoshiRulz|talk]]) 19:09, 16 October 2026 (UTC) a0q3aib8vvo4cws00wuj7bmdjehxdgx 334027 334021 2026-10-28T06:57:55Z YoshiRulz 10156 /* English label */ Reply 334027 wikitext text/x-wiki {{type documentation|Z23|Nothing |related types= * {{Z+|Z22}} * {{Z+|Z5}} * {{Z+|Z21}} |cardinality=Valid: {{formatnum:0}} <br>Type admits: {{formatnum:1}} |proposal=<!--N/A--> }} == English label == I've just fixed a handful of cases where someone had tried to insert a literal Z23 in a composition, presumably by entering <q>nothing</q> into the Type field. If we swapped out its label for one of its aliases, like <q>Unreachable</q>, that should prevent further mistakes. (It would also free up the term <q>nothing</q> in case [[WT:Naming_conventions#Void_is_meaningless|we want to use that for Z24's label]].) [[User:YoshiRulz|YoshiRulz]] ([[User talk:YoshiRulz|talk]]) 06:27, 26 May 2026 (UTC) :@[[User:YoshiRulz|YoshiRulz]]: This is not "unreachable", though, and it's intentionally distinct from Z24 in the type system. [[User:Jdforrester (WMF)|Jdforrester (WMF)]] ([[User talk:Jdforrester (WMF)|talk]]) 16:59, 1 June 2026 (UTC) :Found and fixed more. I've changed the label to "Never". [[User:YoshiRulz|YoshiRulz]] ([[User talk:YoshiRulz|talk]]) 19:00, 16 October 2026 (UTC) ::I don't think that's semantically correct. [[User:Jdforrester (WMF)|Jdforrester (WMF)]] ([[User talk:Jdforrester (WMF)|talk]]) 23:45, 27 October 2026 (UTC) :::How do you mean? It makes about as much sense to say <q>&lt;some function&gt; returns never</q> as <q>&lt;some function&gt; returns string</q>. PHP and TypeScript, among others, use 'never' for the empty type. [[User:YoshiRulz|YoshiRulz]] ([[User talk:YoshiRulz|talk]]) 06:57, 28 October 2026 (UTC) == Purpose == Why do we need an empty type?<br>In type-theoretic systems, the empty type is necessary to express impossibilities or contradictions. {{SITENAME}} is not a theorem prover.<br>In strongly-typed languages, a subroutine which throws has return type <code>Never</code>. {{SITENAME}} has out-of-band error handling but is dynamically-typed&mdash;the return type of {{Z|851}} is currently {{Z|1}} so that the editor will allow you to use it anywhere, but it wouldn't really matter if it were {{Z|23}} or {{Z|21}} since ''no value is ever returned''. [[User:YoshiRulz|YoshiRulz]] ([[User talk:YoshiRulz|talk]]) 19:09, 16 October 2026 (UTC) ljq2duo1ka2j8wafz8qd2y9t2jyj481 334028 334027 2026-10-28T07:03:36Z YoshiRulz 10156 /* Purpose */ 334028 wikitext text/x-wiki {{type documentation|Z23|Nothing |related types= * {{Z+|Z22}} * {{Z+|Z5}} * {{Z+|Z21}} |cardinality=Valid: {{formatnum:0}} <br>Type admits: {{formatnum:1}} |proposal=<!--N/A--> }} == English label == I've just fixed a handful of cases where someone had tried to insert a literal Z23 in a composition, presumably by entering <q>nothing</q> into the Type field. If we swapped out its label for one of its aliases, like <q>Unreachable</q>, that should prevent further mistakes. (It would also free up the term <q>nothing</q> in case [[WT:Naming_conventions#Void_is_meaningless|we want to use that for Z24's label]].) [[User:YoshiRulz|YoshiRulz]] ([[User talk:YoshiRulz|talk]]) 06:27, 26 May 2026 (UTC) :@[[User:YoshiRulz|YoshiRulz]]: This is not "unreachable", though, and it's intentionally distinct from Z24 in the type system. [[User:Jdforrester (WMF)|Jdforrester (WMF)]] ([[User talk:Jdforrester (WMF)|talk]]) 16:59, 1 June 2026 (UTC) :Found and fixed more. I've changed the label to "Never". [[User:YoshiRulz|YoshiRulz]] ([[User talk:YoshiRulz|talk]]) 19:00, 16 October 2026 (UTC) ::I don't think that's semantically correct. [[User:Jdforrester (WMF)|Jdforrester (WMF)]] ([[User talk:Jdforrester (WMF)|talk]]) 23:45, 27 October 2026 (UTC) :::How do you mean? It makes about as much sense to say <q>&lt;some function&gt; returns never</q> as <q>&lt;some function&gt; returns string</q>. PHP and TypeScript, among others, use 'never' for the empty type. [[User:YoshiRulz|YoshiRulz]] ([[User talk:YoshiRulz|talk]]) 06:57, 28 October 2026 (UTC) == Purpose == Why do we need an empty type?<br>In type-theoretic systems, the empty type is necessary to express impossibilities or contradictions. {{SITENAME}} is not a theorem prover.<br>In statically-typed languages, a subroutine which throws has return type <code>Never</code>. {{SITENAME}} has out-of-band error handling but is dynamically-typed&mdash;the return type of {{Z|851}} is currently {{Z|1}} so that the editor will allow you to use it anywhere, but it wouldn't really matter if it were {{Z|23}} or {{Z|21}} since ''no value is ever returned''. No type check will ever happen and a type mismatch error will never be raised. [[User:YoshiRulz|YoshiRulz]] ([[User talk:YoshiRulz|talk]]) 07:03, 28 October 2026 (UTC) ph9nxasmt0pbi3p63feycb18yl9bh96 Z44604 0 97764 333894 333674 2026-10-27T14:06:31Z Satdeep Gill 10395 333894 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z44604" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z44598", "Z14K2": { "Z1K1": "Z7", "Z7K1": "Z27868", "Z27868K1": { "Z1K1": "Z7", "Z7K1": "Z21394", "Z21394K1": [ "Z6", { "Z1K1": "Z7", "Z7K1": "Z802", "Z802K1": { "Z1K1": "Z7", "Z7K1": "Z844", "Z844K1": { "Z1K1": "Z7", "Z7K1": "Z44378", "Z44378K1": { "Z1K1": "Z18", "Z18K1": "Z44598K1" }, "Z44378K2": { "Z1K1": "Z18", "Z18K1": "Z44598K3" } }, "Z844K2": { "Z1K1": "Z40", "Z40K1": "Z41" } }, "Z802K2": "The ", "Z802K3": "" }, { "Z1K1": "Z7", "Z7K1": "Z23468", "Z23468K1": { "Z1K1": "Z7", "Z7K1": "Z6821", "Z6821K1": { "Z1K1": "Z18", "Z18K1": "Z44598K1" } }, "Z23468K2": { "Z1K1": "Z18", "Z18K1": "Z44598K3" } }, { "Z1K1": "Z7", "Z7K1": "Z802", "Z802K1": { "Z1K1": "Z7", "Z7K1": "Z844", "Z844K1": { "Z1K1": "Z7", "Z7K1": "Z44378", "Z44378K1": { "Z1K1": "Z18", "Z18K1": "Z44598K1" }, "Z44378K2": { "Z1K1": "Z18", "Z18K1": "Z44598K3" } }, "Z844K2": { "Z1K1": "Z40", "Z40K1": "Z41" } }, "Z802K2": " are ", "Z802K3": " is " }, { "Z1K1": "Z7", "Z7K1": "Z46899", "Z46899K1": { "Z1K1": "Z7", "Z7K1": "Z101", "Z101K1": { "Z1K1": "Z7", "Z7K1": "Z802", "Z802K1": { "Z1K1": "Z7", "Z7K1": "Z844", "Z844K1": { "Z1K1": "Z7", "Z7K1": "Z44378", "Z44378K1": { "Z1K1": "Z18", "Z18K1": "Z44598K1" }, "Z44378K2": { "Z1K1": "Z18", "Z18K1": "Z44598K3" } }, "Z844K2": { "Z1K1": "Z40", "Z40K1": "Z41" } }, "Z802K2": { "Z1K1": "Z7", "Z7K1": "Z873", "Z873K1": "Z47861", "Z873K2": { "Z1K1": "Z7", "Z7K1": "Z13464", "Z13464K1": "Z23753", "Z13464K2": { "Z1K1": "Z18", "Z18K1": "Z44598K2" }, "Z13464K3": { "Z1K1": "Z18", "Z18K1": "Z44598K3" } } }, "Z802K3": { "Z1K1": "Z7", "Z7K1": "Z873", "Z873K1": "Z38814", "Z873K2": { "Z1K1": "Z7", "Z7K1": "Z13464", "Z13464K1": "Z23753", "Z13464K2": { "Z1K1": "Z18", "Z18K1": "Z44598K2" }, "Z13464K3": { "Z1K1": "Z18", "Z18K1": "Z44598K3" } } } } }, "Z46899K2": { "Z1K1": "Z18", "Z18K1": "Z44598K3" } }, " ." ] } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "entity is instance of multiple classes,Composition" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "English composition for entity is instance of multiple classes" } ] } } sihedzhdxb785xbwokt53ebdu4bo60t 333895 333894 2026-10-27T14:07:07Z Satdeep Gill 10395 333895 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z44604" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z44598", "Z14K2": { "Z1K1": "Z7", "Z7K1": "Z27868", "Z27868K1": { "Z1K1": "Z7", "Z7K1": "Z21394", "Z21394K1": [ "Z6", { "Z1K1": "Z7", "Z7K1": "Z802", "Z802K1": { "Z1K1": "Z7", "Z7K1": "Z844", "Z844K1": { "Z1K1": "Z7", "Z7K1": "Z44378", "Z44378K1": { "Z1K1": "Z18", "Z18K1": "Z44598K1" }, "Z44378K2": { "Z1K1": "Z18", "Z18K1": "Z44598K3" } }, "Z844K2": { "Z1K1": "Z40", "Z40K1": "Z41" } }, "Z802K2": "The ", "Z802K3": "" }, { "Z1K1": "Z7", "Z7K1": "Z23468", "Z23468K1": { "Z1K1": "Z7", "Z7K1": "Z6821", "Z6821K1": { "Z1K1": "Z18", "Z18K1": "Z44598K1" } }, "Z23468K2": { "Z1K1": "Z18", "Z18K1": "Z44598K3" } }, { "Z1K1": "Z7", "Z7K1": "Z802", "Z802K1": { "Z1K1": "Z7", "Z7K1": "Z844", "Z844K1": { "Z1K1": "Z7", "Z7K1": "Z44378", "Z44378K1": { "Z1K1": "Z18", "Z18K1": "Z44598K1" }, "Z44378K2": { "Z1K1": "Z18", "Z18K1": "Z44598K3" } }, "Z844K2": { "Z1K1": "Z40", "Z40K1": "Z41" } }, "Z802K2": " are ", "Z802K3": " is " }, { "Z1K1": "Z7", "Z7K1": "Z46899", "Z46899K1": { "Z1K1": "Z7", "Z7K1": "Z101", "Z101K1": { "Z1K1": "Z7", "Z7K1": "Z802", "Z802K1": { "Z1K1": "Z7", "Z7K1": "Z844", "Z844K1": { "Z1K1": "Z7", "Z7K1": "Z44378", "Z44378K1": { "Z1K1": "Z18", "Z18K1": "Z44598K1" }, "Z44378K2": { "Z1K1": "Z18", "Z18K1": "Z44598K3" } }, "Z844K2": { "Z1K1": "Z40", "Z40K1": "Z41" } }, "Z802K2": { "Z1K1": "Z7", "Z7K1": "Z873", "Z873K1": "Z47861", "Z873K2": { "Z1K1": "Z7", "Z7K1": "Z13464", "Z13464K1": "Z23753", "Z13464K2": { "Z1K1": "Z18", "Z18K1": "Z44598K2" }, "Z13464K3": { "Z1K1": "Z18", "Z18K1": "Z44598K3" } } }, "Z802K3": { "Z1K1": "Z7", "Z7K1": "Z873", "Z873K1": "Z38814", "Z873K2": { "Z1K1": "Z7", "Z7K1": "Z13464", "Z13464K1": "Z23753", "Z13464K2": { "Z1K1": "Z18", "Z18K1": "Z44598K2" }, "Z13464K3": { "Z1K1": "Z18", "Z18K1": "Z44598K3" } } } } }, "Z46899K2": { "Z1K1": "Z18", "Z18K1": "Z44598K3" } }, "." ] } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "entity is instance of multiple classes,Composition" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "English composition for entity is instance of multiple classes" } ] } } 8ni4se6irfcgd69edup40s53bmw9vt0 Z46989 0 100620 333888 331543 2026-10-27T12:16:19Z Jsamwrites 938 Added Z47963 and Z47964 to the approved list of test cases 333888 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z46989" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z46989K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z46989K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } }, { "Z1K1": "Z17", "Z17K1": { "Z1K1": "Z7", "Z7K1": "Z881", "Z881K1": "Z39328" }, "Z17K2": "Z46989K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "variant" } ] } } ], "Z8K2": "Z11", "Z8K3": [ "Z20", "Z46991", "Z46992", "Z46993", "Z46994", "Z46995", "Z46996", "Z47963", "Z47964" ], "Z8K4": [ "Z14", "Z46990" ], "Z8K5": "Z46989" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Founder sentence" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Sentence saying who founded the item (P112, founder), in the past: passive by default (The Wikimedia Foundation was founded by Jimmy Wales), active with the variant voice: active voice." } ] } } 1gkppbxeg0swcikle2ahtdl6p0m3dfw Z47099 0 100730 333930 332113 2026-10-27T19:18:54Z Jsamwrites 938 Added Z47985, Z47986 and Z47987 to the approved list of test cases 333930 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47099" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z47099K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z47099K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } }, { "Z1K1": "Z17", "Z17K1": { "Z1K1": "Z7", "Z7K1": "Z881", "Z881K1": "Z39328" }, "Z17K2": "Z47099K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "variant" } ] } } ], "Z8K2": "Z11", "Z8K3": [ "Z20", "Z47101", "Z47102", "Z47985", "Z47986", "Z47987" ], "Z8K4": [ "Z14", "Z47100" ], "Z8K5": "Z47099" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Publication date sentence" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Sentence saying when the item was published (P577), in the past: Les Misérables was published in 1862." } ] } } aa6bdkxehq1pj294c92oemvclmeazbk 333934 333930 2026-10-27T19:20:00Z Jsamwrites 938 Added Z47988 and Z47989 to the approved list of test cases 333934 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47099" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z47099K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z47099K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } }, { "Z1K1": "Z17", "Z17K1": { "Z1K1": "Z7", "Z7K1": "Z881", "Z881K1": "Z39328" }, "Z17K2": "Z47099K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "variant" } ] } } ], "Z8K2": "Z11", "Z8K3": [ "Z20", "Z47101", "Z47102", "Z47985", "Z47986", "Z47987", "Z47988", "Z47989" ], "Z8K4": [ "Z14", "Z47100" ], "Z8K5": "Z47099" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Publication date sentence" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Sentence saying when the item was published (P577), in the past: Les Misérables was published in 1862." } ] } } seo6khk7v7uqaslhzhgmzjqe58uii1x Z47127 0 100758 333905 331868 2026-10-27T16:25:22Z ReXLer 39813 Added Z47982 to the approved list of test cases 333905 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47127" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6001", "Z17K2": "Z47127K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z47127K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } } ], "Z8K2": "Z40", "Z8K3": [ "Z20", "Z47129", "Z47130", "Z47982" ], "Z8K4": [ "Z14", "Z47128" ], "Z8K5": "Z47127" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "is this proper noun plural? (using Z47117)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } iq5zilfsc5un3qxfj0542ougnnwp0re Z47251 0 100886 333887 332405 2026-10-27T12:15:53Z Jsamwrites 938 Added Z47960, Z47961 and Z47962 to the approved list of test cases 333887 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47251" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z47251K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" }, { "Z1K1": "Z11", "Z11K1": "Z1078", "Z11K2": "butir" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z47251K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" }, { "Z1K1": "Z11", "Z11K1": "Z1078", "Z11K2": "bahasa" } ] } }, { "Z1K1": "Z17", "Z17K1": { "Z1K1": "Z7", "Z7K1": "Z881", "Z881K1": "Z39328" }, "Z17K2": "Z47251K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "variant" }, { "Z1K1": "Z11", "Z11K1": "Z1078", "Z11K2": "varian" } ] } } ], "Z8K2": "Z11", "Z8K3": [ "Z20", "Z47350", "Z47960", "Z47961", "Z47962" ], "Z8K4": [ "Z14", "Z47252" ], "Z8K5": "Z47251" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Classification sentence" }, { "Z1K1": "Z11", "Z11K1": "Z1078", "Z11K2": "Kalimat klasifikasi" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Sentence about the item for the property P31: what kind of thing the item is (instance of): Paris is a city. Variant: a list of feature pairs (voice; referring expression → personal pronoun for It is …); empty for the default sentence." }, { "Z1K1": "Z11", "Z11K1": "Z1078", "Z11K2": "Kalimat mengenai butir untuk atribut P31: apa jenis dari butir tersebut (adalah): Paris adalah kota. \nVarian: suatu daftar pasangan fitur; kosong untuk kalimat baku." } ] } } 7y9zrfmiwgrn0l56634ua127nivjy1b Z47282 0 100918 334030 333857 2026-10-28T07:08:07Z Jsamwrites 938 Added Z48006 and Z48007 to the approved list of test cases 334030 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47282" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z47282K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z47282K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } }, { "Z1K1": "Z17", "Z17K1": { "Z1K1": "Z7", "Z7K1": "Z881", "Z881K1": "Z39328" }, "Z17K2": "Z47282K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "variant" } ] } } ], "Z8K2": "Z11", "Z8K3": [ "Z20", "Z47952", "Z47953", "Z47954", "Z48006", "Z48007" ], "Z8K4": [ "Z14", "Z47283" ], "Z8K5": "Z47282" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Follows sentence" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Sentence about the item for the property P155: what the item follows: June follows May. Variant: a list of feature pairs (voice; referring expression → personal pronoun for It is …); empty for the default sentence." } ] } } 9vfv2xu1kpcekf4z3619up2vbtp1t6w Z47284 0 100920 334029 333858 2026-10-28T07:07:57Z Jsamwrites 938 Added Z48008, Z48009 and Z48010 to the approved list of test cases 334029 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47284" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z47284K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z47284K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } }, { "Z1K1": "Z17", "Z17K1": { "Z1K1": "Z7", "Z7K1": "Z881", "Z881K1": "Z39328" }, "Z17K2": "Z47284K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "variant" } ] } } ], "Z8K2": "Z11", "Z8K3": [ "Z20", "Z47956", "Z48008", "Z48009", "Z48010" ], "Z8K4": [ "Z14", "Z47285" ], "Z8K5": "Z47284" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Followed by sentence" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Sentence about the item for the property P156: what follows the item: June is followed by July. Variant: a list of feature pairs (voice; referring expression → personal pronoun for It is …); empty for the default sentence." } ] } } omkgc3tvzif2yjltyoirsa0wiff4o8t Z47472 0 101120 333889 332786 2026-10-27T12:16:31Z Jsamwrites 938 Added Z47965, Z47966, Z47967, Z47968, Z47969 and Z47970 to the approved list of test cases 333889 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47472" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z47472K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z47472K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } }, { "Z1K1": "Z17", "Z17K1": { "Z1K1": "Z7", "Z7K1": "Z881", "Z881K1": "Z39328" }, "Z17K2": "Z47472K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "variant" } ] } } ], "Z8K2": "Z11", "Z8K3": [ "Z20", "Z47482", "Z47965", "Z47966", "Z47967", "Z47968", "Z47969", "Z47970" ], "Z8K4": [ "Z14", "Z47473" ], "Z8K5": "Z47472" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Programming language sentence" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Sentence about the item for the property P277: the programming languages the item is written in: Inkscape is written in C++ and C. Variant: a list of feature pairs (voice; referring expression → personal pronoun for It is …); empty for the default sentence." } ] } } qaf42ygjdor1jta47pn0y5jmbw67vt7 Z47474 0 101122 333890 332788 2026-10-27T12:16:41Z Jsamwrites 938 Added Z47971, Z47972, Z47973, Z47974, Z47975 and Z47976 to the approved list of test cases 333890 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47474" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z47474K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z47474K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } }, { "Z1K1": "Z17", "Z17K1": { "Z1K1": "Z7", "Z7K1": "Z881", "Z881K1": "Z39328" }, "Z17K2": "Z47474K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "variant" } ] } } ], "Z8K2": "Z11", "Z8K3": [ "Z20", "Z47483", "Z47971", "Z47972", "Z47973", "Z47974", "Z47975", "Z47976" ], "Z8K4": [ "Z14", "Z47475" ], "Z8K5": "Z47474" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Operating system sentence" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Sentence about the item for the property P306: the operating systems the item runs on: Inkscape runs on Linux, Windows and others. Variant: a list of feature pairs (voice; referring expression → personal pronoun for It is …); empty for the default sentence." } ] } } askh8jxsyautfyd7uadhcl8tsgp1unx Z47647 0 101301 333913 333724 2026-10-27T19:03:45Z Jsamwrites 938 Added Z47984 to the approved list of test cases 333913 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47647" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z47647K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z47647K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } }, { "Z1K1": "Z17", "Z17K1": { "Z1K1": "Z7", "Z7K1": "Z881", "Z881K1": "Z39328" }, "Z17K2": "Z47647K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "variant" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20", "Z47736", "Z47838", "Z47839", "Z47840", "Z47984" ], "Z8K4": [ "Z14", "Z47648" ], "Z8K5": "Z47647" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Founder sentence (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Generates HTML with links and a language marker for: Sentence saying who founded the item (P112, founder), in the past: passive by default (The Wikimedia Foundation was founded by Jimmy Wales), active with the variant voice: active voice." } ] } } jhatsadugmps86ynpqrknvie59pldmj Z47653 0 101307 333902 333245 2026-10-27T16:17:58Z Jsamwrites 938 Added Z47977, Z47978, Z47979 and Z47980 to the approved list of test cases 333902 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47653" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z47653K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z47653K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } }, { "Z1K1": "Z17", "Z17K1": { "Z1K1": "Z7", "Z7K1": "Z881", "Z881K1": "Z39328" }, "Z17K2": "Z47653K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "variant" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20", "Z47739", "Z47977", "Z47978", "Z47979", "Z47980" ], "Z8K4": [ "Z14", "Z47654" ], "Z8K5": "Z47653" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Programming language sentence (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Generates HTML with links and a language marker for: Sentence about the item for the property P277: the programming languages the item is written in: Inkscape is written in C++ and C. Variant: a list of feature pairs (voice; referring expression → personal pronoun for It is …); empty for the default sentence." } ] } } g9jvg20js09tu8n9jue4vpqrz5ifdne Z47655 0 101309 333903 333244 2026-10-27T16:18:14Z Jsamwrites 938 Added Z47981 to the approved list of test cases 333903 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47655" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z47655K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z47655K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } }, { "Z1K1": "Z17", "Z17K1": { "Z1K1": "Z7", "Z7K1": "Z881", "Z881K1": "Z39328" }, "Z17K2": "Z47655K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "variant" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20", "Z47740", "Z47981" ], "Z8K4": [ "Z14", "Z47656" ], "Z8K5": "Z47655" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Operating system sentence (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Generates HTML with links and a language marker for: Sentence about the item for the property P306: the operating systems the item runs on: Inkscape runs on Linux, Windows and others. Variant: a list of feature pairs (voice; referring expression → personal pronoun for It is …); empty for the default sentence." } ] } } 0iigyjtrid8yhnni76th8rpu9rzzw3y 333914 333903 2026-10-27T19:04:06Z Jsamwrites 938 Added Z47983 to the approved list of test cases 333914 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47655" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z47655K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z47655K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } }, { "Z1K1": "Z17", "Z17K1": { "Z1K1": "Z7", "Z7K1": "Z881", "Z881K1": "Z39328" }, "Z17K2": "Z47655K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "variant" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20", "Z47740", "Z47981", "Z47983" ], "Z8K4": [ "Z14", "Z47656" ], "Z8K5": "Z47655" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Operating system sentence (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Generates HTML with links and a language marker for: Sentence about the item for the property P306: the operating systems the item runs on: Inkscape runs on Linux, Windows and others. Variant: a list of feature pairs (voice; referring expression → personal pronoun for It is …); empty for the default sentence." } ] } } 9r7hzhusvby16kiyrmd0qlp2r76mp9q 333961 333914 2026-10-27T20:11:56Z Jsamwrites 938 Added Z47990 to the approved list of test cases 333961 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47655" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z47655K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z47655K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } }, { "Z1K1": "Z17", "Z17K1": { "Z1K1": "Z7", "Z7K1": "Z881", "Z881K1": "Z39328" }, "Z17K2": "Z47655K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "variant" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20", "Z47740", "Z47981", "Z47983", "Z47990" ], "Z8K4": [ "Z14", "Z47656" ], "Z8K5": "Z47655" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Operating system sentence (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Generates HTML with links and a language marker for: Sentence about the item for the property P306: the operating systems the item runs on: Inkscape runs on Linux, Windows and others. Variant: a list of feature pairs (voice; referring expression → personal pronoun for It is …); empty for the default sentence." } ] } } qe3m4odpv8vs116nhc1wud6w9s7cv4d Z47685 0 101339 333965 333265 2026-10-27T20:13:03Z Jsamwrites 938 Added Z47991 to the approved list of test cases 333965 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47685" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z47685K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z47685K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } }, { "Z1K1": "Z17", "Z17K1": { "Z1K1": "Z7", "Z7K1": "Z881", "Z881K1": "Z39328" }, "Z17K2": "Z47685K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "variant" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20", "Z47760", "Z47991" ], "Z8K4": [ "Z14", "Z47686" ], "Z8K5": "Z47685" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Depends on sentence (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Generates HTML with links and a language marker for: Sentence about the item for the property P1547: what the software depends on: LaTeX depends on TeX. Variant: a list of feature pairs (voice; referring expression → personal pronoun for It is …); empty for the default sentence." } ] } } 0mc1d7mzorj5p79jwwklo5a9c0zfgkg Z47687 0 101341 333964 333240 2026-10-27T20:12:51Z Jsamwrites 938 Added Z47992 to the approved list of test cases 333964 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47687" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z47687K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z47687K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } }, { "Z1K1": "Z17", "Z17K1": { "Z1K1": "Z7", "Z7K1": "Z881", "Z881K1": "Z39328" }, "Z17K2": "Z47687K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "variant" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20", "Z47744", "Z47992" ], "Z8K4": [ "Z14", "Z47688" ], "Z8K5": "Z47687" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Platform sentence (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Generates HTML with links and a language marker for: Sentence about the item for the property P400: the platform the item runs on. Variant: a list of feature pairs (voice; referring expression → personal pronoun for It is …); empty for the default sentence." } ] } } 19u89ew0npe9j4y62enimes8wt85i3h Z47705 0 101359 333963 333237 2026-10-27T20:12:37Z Jsamwrites 938 Added Z47993 to the approved list of test cases 333963 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47705" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z47705K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z47705K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } }, { "Z1K1": "Z17", "Z17K1": { "Z1K1": "Z7", "Z7K1": "Z881", "Z881K1": "Z39328" }, "Z17K2": "Z47705K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "variant" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20", "Z47748", "Z47993" ], "Z8K4": [ "Z14", "Z47706" ], "Z8K5": "Z47705" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Software engine sentence (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Generates HTML with links and a language marker for: Sentence about the item for the property P408: the software engine the item uses: Wikipedia uses MediaWiki. Variant: a list of feature pairs (voice; referring expression → personal pronoun for It is …); empty for the default sentence." } ] } } h9zmmdinneyfdhwrax2p8alf3ua0h4q Z47715 0 101369 333962 333566 2026-10-27T20:12:13Z Jsamwrites 938 Added Z47994 to the approved list of test cases 333962 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47715" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z47715K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z47715K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } }, { "Z1K1": "Z17", "Z17K1": { "Z1K1": "Z7", "Z7K1": "Z881", "Z881K1": "Z39328" }, "Z17K2": "Z47715K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "variant" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20", "Z47828", "Z47994" ], "Z8K4": [ "Z14", "Z47716" ], "Z8K5": "Z47715" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Licence sentence (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Generates HTML with links and a language marker for: Sentence about the item for the property P275: the licence the work is released under. Variant: a list of feature pairs (voice; referring expression → personal pronoun for It is …); empty for the default sentence." } ] } } 4ei8496u4xtuuct8zk350bn9ye6kcwb Wikifunctions:Status updates/2026-10-25/de 4 101489 333912 333505 2026-10-27T19:03:28Z Ameisenigel 44 Created page with "=== Wikiabstrak-App ===" 333912 wikitext text/x-wiki <languages/> {{Wikifunctions updates | prevlabel = Vorheriges Update | prev = 2026-10-17 | nextlabel = Nächstes Update | next = }} <span id="Wikiabstrak_app"></span> === Wikiabstrak-App === [[File:Screenshot of Wikiabstrak App.png|thumb|Wikiabstrak App]] <div lang="en" dir="ltr" class="mw-content-ltr"> A new app has been developed by [[:meta:User:Affandy Murad|Affandy Murad]], a volunteer on Indonesian Wikipedia and other projects: [https://wikiabstrak.web.app/ Wikiabstrak]. </div> <div lang="en" dir="ltr" class="mw-content-ltr"> The app itself describes it as such: </div> <div lang="en" dir="ltr" class="mw-content-ltr"> ''“Wikiabstrak is an open experiment that turns structured Wikidata into readable summaries, without any language model (LLM). Search for a country, place, person or building and it assembles a paragraph from Wikidata claims using fixed rules, so every sentence can be traced back to its source.'' </div> <div lang="en" dir="ltr" class="mw-content-ltr"> ''“It also shows key facts, photos from Wikimedia Commons, links to every Wikimedia project, and a ready-made lead-paragraph recipe for Abstract Wikipedia, so you can start or edit language-independent articles.”'' </div> <div lang="en" dir="ltr" class="mw-content-ltr"> Enjoy using the app! If you have suggestions, you can reach Affandy in project telegram / IRC chat, or on [[:meta:User talk:Affandy Murad|his user talk page]]. Also check out the other apps that Affandy has created and that are listed on [[:meta:User:Affandy Murad|his userpage]]. </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === No changes in the software this week === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> Due to the [[:en:PHP2Shell|PHP vulnerabilities]] published this week, we decided to skip deployment beyond safety critical changes. </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === Recording of October Volunteer’s Corner === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> This month’s volunteers’ corner meeting (12 October 2026) is [[:commons:File:Abstract Wikipedia Volunteer Corner 2026-10.webm|now available as a recording on Commons]]. Thank you for the lively discussion and new ideas! </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === Next Volunteers’ Corner on November 9 at 11 UTC === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> The next Volunteers’ Corner will be on [https://zonestamp.toolforge.org/1794222000 Monday, 9 November 2026 at 11:00 UTC]. Note the earlier time in the day, in order to make it easier for some folks to attend this one. We plan to have the following agenda: there will be time to ask questions and discuss all matters arising. If we have time, we will write a function together. Everyone is welcome to join us on [https://meet.google.com/xuy-njxh-rkw Google Meet]. </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === Fresh Functions weekly: 169 new Functions === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> This week we had 169 new functions. Here is an incomplete list of functions with implementations and passing tests to get a taste of what functions have been created. Thanks everybody for contributing! </div> * {{Z|Z45336}} * {{Z|Z45338}} * {{Z|Z45343}} * {{Z|Z45347}} * {{Z|Z45350}} * {{Z|Z45353}} * {{Z|Z45356}} * {{Z|Z45370}} * {{Z|Z45381}} * {{Z|Z45387}} * {{Z|Z45390}} * {{Z|Z45392}} * {{Z|Z45400}} * {{Z|Z45402}} * {{Z|Z45406}} * {{Z|Z45408}} * {{Z|Z45410}} * {{Z|Z45413}} * {{Z|Z45415}} * {{Z|Z45417}} * {{Z|Z45420}} * {{Z|Z45422}} * {{Z|Z45424}} * {{Z|Z45429}} * {{Z|Z45431}} * {{Z|Z45434}} * {{Z|Z45456}} * {{Z|Z45457}} * {{Z|Z45481}} * {{Z|Z45485}} * {{Z|Z45491}} * {{Z|Z45495}} * {{Z|Z45510}} * {{Z|Z45515}} * {{Z|Z45517}} * {{Z|Z45527}} * {{Z|Z45549}} * {{Z|Z45575}} * {{Z|Z45588}} * {{Z|Z45590}} * {{Z|Z45605}} * {{Z|Z45612}} * {{Z|Z45617}} * {{Z|Z45644}} * {{Z|Z45648}} * {{Z|Z45663}} * {{Z|Z45702}} * {{Z|Z45723}} * {{Z|Z45739}} * {{Z|Z45751}} * {{Z|Z45763}} * {{Z|Z45775}} * {{Z|Z45776}} * {{Z|Z45777}} * {{Z|Z45778}} * {{Z|Z45779}} * {{Z|Z45780}} * {{Z|Z45781}} * {{Z|Z45782}} * {{Z|Z45783}} * {{Z|Z45784}} * {{Z|Z45785}} * {{Z|Z45786}} * {{Z|Z45787}} * {{Z|Z45788}} * {{Z|Z45790}} * {{Z|Z45792}} * {{Z|Z45793}} * {{Z|Z45795}} * {{Z|Z45796}} * {{Z|Z45798}} * {{Z|Z45799}} * {{Z|Z45836}} * {{Z|Z45943}} * {{Z|Z45955}} * {{Z|Z45981}} * {{Z|Z45982}} * {{Z|Z45983}} * {{Z|Z45984}} * {{Z|Z45985}} * {{Z|Z45986}} * {{Z|Z45987}} * {{Z|Z45988}} * {{Z|Z45990}} * {{Z|Z45992}} * {{Z|Z45994}} * {{Z|Z45995}} * {{Z|Z45996}} * {{Z|Z46058}} * {{Z|Z46069}} * {{Z|Z46070}} * {{Z|Z46071}} * {{Z|Z46072}} * {{Z|Z46073}} * {{Z|Z46074}} * {{Z|Z46075}} * {{Z|Z46076}} * {{Z|Z46077}} * {{Z|Z46078}} * {{Z|Z46079}} * {{Z|Z46096}} * {{Z|Z46118}} * {{Z|Z46130}} * {{Z|Z46140}} * {{Z|Z46150}} * {{Z|Z46162}} * {{Z|Z46171}} * {{Z|Z46205}} * {{Z|Z46243}} * {{Z|Z46291}} * {{Z|Z46292}} * {{Z|Z46311}} * {{Z|Z46322}} * {{Z|Z46323}} * {{Z|Z46324}} * {{Z|Z46325}} * {{Z|Z46365}} * {{Z|Z46391}} * {{Z|Z46392}} * {{Z|Z46393}} * {{Z|Z46394}} * {{Z|Z46395}} * {{Z|Z46420}} * {{Z|Z46432}} * {{Z|Z46448}} * {{Z|Z46460}} * {{Z|Z46499}} * {{Z|Z46508}} * {{Z|Z46509}} * {{Z|Z46532}} * {{Z|Z46535}} * {{Z|Z46536}} * {{Z|Z46558}} * {{Z|Z46561}} * {{Z|Z46568}} * {{Z|Z46569}} * {{Z|Z46570}} * {{Z|Z46602}} * {{Z|Z46616}} * {{Z|Z46617}} * {{Z|Z46641}} * {{Z|Z46657}} * {{Z|Z46658}} * {{Z|Z46659}} * {{Z|Z46673}} * {{Z|Z46685}} <span lang="en" dir="ltr" class="mw-content-ltr">A [https://www.wikifunctions.org/wiki/Special:ListObjectsByType?type=Z8&orderby=latest complete list of all functions sorted by when they were created] is available.</span> [[Category:Status updates{{#translation:}}|2026-10-25]] a4i63acgrct31odb6odq7dkj5rl3h7l 333916 333912 2026-10-27T19:04:15Z Ameisenigel 44 Created page with "Eine neue App wurde von [[$1|Affandy Murad]], einem Freiwilligen in der indonesischen Wikipedia und anderen Projekten, entwickelt: [$2 Wikiabstrak]." 333916 wikitext text/x-wiki <languages/> {{Wikifunctions updates | prevlabel = Vorheriges Update | prev = 2026-10-17 | nextlabel = Nächstes Update | next = }} <span id="Wikiabstrak_app"></span> === Wikiabstrak-App === [[File:Screenshot of Wikiabstrak App.png|thumb|Wikiabstrak App]] Eine neue App wurde von [[:meta:User:Affandy Murad|Affandy Murad]], einem Freiwilligen in der indonesischen Wikipedia und anderen Projekten, entwickelt: [https://wikiabstrak.web.app/ Wikiabstrak]. <div lang="en" dir="ltr" class="mw-content-ltr"> The app itself describes it as such: </div> <div lang="en" dir="ltr" class="mw-content-ltr"> ''“Wikiabstrak is an open experiment that turns structured Wikidata into readable summaries, without any language model (LLM). Search for a country, place, person or building and it assembles a paragraph from Wikidata claims using fixed rules, so every sentence can be traced back to its source.'' </div> <div lang="en" dir="ltr" class="mw-content-ltr"> ''“It also shows key facts, photos from Wikimedia Commons, links to every Wikimedia project, and a ready-made lead-paragraph recipe for Abstract Wikipedia, so you can start or edit language-independent articles.”'' </div> <div lang="en" dir="ltr" class="mw-content-ltr"> Enjoy using the app! If you have suggestions, you can reach Affandy in project telegram / IRC chat, or on [[:meta:User talk:Affandy Murad|his user talk page]]. Also check out the other apps that Affandy has created and that are listed on [[:meta:User:Affandy Murad|his userpage]]. </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === No changes in the software this week === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> Due to the [[:en:PHP2Shell|PHP vulnerabilities]] published this week, we decided to skip deployment beyond safety critical changes. </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === Recording of October Volunteer’s Corner === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> This month’s volunteers’ corner meeting (12 October 2026) is [[:commons:File:Abstract Wikipedia Volunteer Corner 2026-10.webm|now available as a recording on Commons]]. Thank you for the lively discussion and new ideas! </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === Next Volunteers’ Corner on November 9 at 11 UTC === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> The next Volunteers’ Corner will be on [https://zonestamp.toolforge.org/1794222000 Monday, 9 November 2026 at 11:00 UTC]. Note the earlier time in the day, in order to make it easier for some folks to attend this one. We plan to have the following agenda: there will be time to ask questions and discuss all matters arising. If we have time, we will write a function together. Everyone is welcome to join us on [https://meet.google.com/xuy-njxh-rkw Google Meet]. </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === Fresh Functions weekly: 169 new Functions === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> This week we had 169 new functions. Here is an incomplete list of functions with implementations and passing tests to get a taste of what functions have been created. Thanks everybody for contributing! </div> * {{Z|Z45336}} * {{Z|Z45338}} * {{Z|Z45343}} * {{Z|Z45347}} * {{Z|Z45350}} * {{Z|Z45353}} * {{Z|Z45356}} * {{Z|Z45370}} * {{Z|Z45381}} * {{Z|Z45387}} * {{Z|Z45390}} * {{Z|Z45392}} * {{Z|Z45400}} * {{Z|Z45402}} * {{Z|Z45406}} * {{Z|Z45408}} * {{Z|Z45410}} * {{Z|Z45413}} * {{Z|Z45415}} * {{Z|Z45417}} * {{Z|Z45420}} * {{Z|Z45422}} * {{Z|Z45424}} * {{Z|Z45429}} * {{Z|Z45431}} * {{Z|Z45434}} * {{Z|Z45456}} * {{Z|Z45457}} * {{Z|Z45481}} * {{Z|Z45485}} * {{Z|Z45491}} * {{Z|Z45495}} * {{Z|Z45510}} * {{Z|Z45515}} * {{Z|Z45517}} * {{Z|Z45527}} * {{Z|Z45549}} * {{Z|Z45575}} * {{Z|Z45588}} * {{Z|Z45590}} * {{Z|Z45605}} * {{Z|Z45612}} * {{Z|Z45617}} * {{Z|Z45644}} * {{Z|Z45648}} * {{Z|Z45663}} * {{Z|Z45702}} * {{Z|Z45723}} * {{Z|Z45739}} * {{Z|Z45751}} * {{Z|Z45763}} * {{Z|Z45775}} * {{Z|Z45776}} * {{Z|Z45777}} * {{Z|Z45778}} * {{Z|Z45779}} * {{Z|Z45780}} * {{Z|Z45781}} * {{Z|Z45782}} * {{Z|Z45783}} * {{Z|Z45784}} * {{Z|Z45785}} * {{Z|Z45786}} * {{Z|Z45787}} * {{Z|Z45788}} * {{Z|Z45790}} * {{Z|Z45792}} * {{Z|Z45793}} * {{Z|Z45795}} * {{Z|Z45796}} * {{Z|Z45798}} * {{Z|Z45799}} * {{Z|Z45836}} * {{Z|Z45943}} * {{Z|Z45955}} * {{Z|Z45981}} * {{Z|Z45982}} * {{Z|Z45983}} * {{Z|Z45984}} * {{Z|Z45985}} * {{Z|Z45986}} * {{Z|Z45987}} * {{Z|Z45988}} * {{Z|Z45990}} * {{Z|Z45992}} * {{Z|Z45994}} * {{Z|Z45995}} * {{Z|Z45996}} * {{Z|Z46058}} * {{Z|Z46069}} * {{Z|Z46070}} * {{Z|Z46071}} * {{Z|Z46072}} * {{Z|Z46073}} * {{Z|Z46074}} * {{Z|Z46075}} * {{Z|Z46076}} * {{Z|Z46077}} * {{Z|Z46078}} * {{Z|Z46079}} * {{Z|Z46096}} * {{Z|Z46118}} * {{Z|Z46130}} * {{Z|Z46140}} * {{Z|Z46150}} * {{Z|Z46162}} * {{Z|Z46171}} * {{Z|Z46205}} * {{Z|Z46243}} * {{Z|Z46291}} * {{Z|Z46292}} * {{Z|Z46311}} * {{Z|Z46322}} * {{Z|Z46323}} * {{Z|Z46324}} * {{Z|Z46325}} * {{Z|Z46365}} * {{Z|Z46391}} * {{Z|Z46392}} * {{Z|Z46393}} * {{Z|Z46394}} * {{Z|Z46395}} * {{Z|Z46420}} * {{Z|Z46432}} * {{Z|Z46448}} * {{Z|Z46460}} * {{Z|Z46499}} * {{Z|Z46508}} * {{Z|Z46509}} * {{Z|Z46532}} * {{Z|Z46535}} * {{Z|Z46536}} * {{Z|Z46558}} * {{Z|Z46561}} * {{Z|Z46568}} * {{Z|Z46569}} * {{Z|Z46570}} * {{Z|Z46602}} * {{Z|Z46616}} * {{Z|Z46617}} * {{Z|Z46641}} * {{Z|Z46657}} * {{Z|Z46658}} * {{Z|Z46659}} * {{Z|Z46673}} * {{Z|Z46685}} <span lang="en" dir="ltr" class="mw-content-ltr">A [https://www.wikifunctions.org/wiki/Special:ListObjectsByType?type=Z8&orderby=latest complete list of all functions sorted by when they were created] is available.</span> [[Category:Status updates{{#translation:}}|2026-10-25]] s6v7ufjmuz99wfcwxg6jxwonm4f6vuq 333918 333916 2026-10-27T19:04:38Z Ameisenigel 44 Created page with "Die App selbst beschreibt sich wie folgt:" 333918 wikitext text/x-wiki <languages/> {{Wikifunctions updates | prevlabel = Vorheriges Update | prev = 2026-10-17 | nextlabel = Nächstes Update | next = }} <span id="Wikiabstrak_app"></span> === Wikiabstrak-App === [[File:Screenshot of Wikiabstrak App.png|thumb|Wikiabstrak App]] Eine neue App wurde von [[:meta:User:Affandy Murad|Affandy Murad]], einem Freiwilligen in der indonesischen Wikipedia und anderen Projekten, entwickelt: [https://wikiabstrak.web.app/ Wikiabstrak]. Die App selbst beschreibt sich wie folgt: <div lang="en" dir="ltr" class="mw-content-ltr"> ''“Wikiabstrak is an open experiment that turns structured Wikidata into readable summaries, without any language model (LLM). Search for a country, place, person or building and it assembles a paragraph from Wikidata claims using fixed rules, so every sentence can be traced back to its source.'' </div> <div lang="en" dir="ltr" class="mw-content-ltr"> ''“It also shows key facts, photos from Wikimedia Commons, links to every Wikimedia project, and a ready-made lead-paragraph recipe for Abstract Wikipedia, so you can start or edit language-independent articles.”'' </div> <div lang="en" dir="ltr" class="mw-content-ltr"> Enjoy using the app! If you have suggestions, you can reach Affandy in project telegram / IRC chat, or on [[:meta:User talk:Affandy Murad|his user talk page]]. Also check out the other apps that Affandy has created and that are listed on [[:meta:User:Affandy Murad|his userpage]]. </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === No changes in the software this week === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> Due to the [[:en:PHP2Shell|PHP vulnerabilities]] published this week, we decided to skip deployment beyond safety critical changes. </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === Recording of October Volunteer’s Corner === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> This month’s volunteers’ corner meeting (12 October 2026) is [[:commons:File:Abstract Wikipedia Volunteer Corner 2026-10.webm|now available as a recording on Commons]]. Thank you for the lively discussion and new ideas! </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === Next Volunteers’ Corner on November 9 at 11 UTC === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> The next Volunteers’ Corner will be on [https://zonestamp.toolforge.org/1794222000 Monday, 9 November 2026 at 11:00 UTC]. Note the earlier time in the day, in order to make it easier for some folks to attend this one. We plan to have the following agenda: there will be time to ask questions and discuss all matters arising. If we have time, we will write a function together. Everyone is welcome to join us on [https://meet.google.com/xuy-njxh-rkw Google Meet]. </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === Fresh Functions weekly: 169 new Functions === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> This week we had 169 new functions. Here is an incomplete list of functions with implementations and passing tests to get a taste of what functions have been created. Thanks everybody for contributing! </div> * {{Z|Z45336}} * {{Z|Z45338}} * {{Z|Z45343}} * {{Z|Z45347}} * {{Z|Z45350}} * {{Z|Z45353}} * {{Z|Z45356}} * {{Z|Z45370}} * {{Z|Z45381}} * {{Z|Z45387}} * {{Z|Z45390}} * {{Z|Z45392}} * {{Z|Z45400}} * {{Z|Z45402}} * {{Z|Z45406}} * {{Z|Z45408}} * {{Z|Z45410}} * {{Z|Z45413}} * {{Z|Z45415}} * {{Z|Z45417}} * {{Z|Z45420}} * {{Z|Z45422}} * {{Z|Z45424}} * {{Z|Z45429}} * {{Z|Z45431}} * {{Z|Z45434}} * {{Z|Z45456}} * {{Z|Z45457}} * {{Z|Z45481}} * {{Z|Z45485}} * {{Z|Z45491}} * {{Z|Z45495}} * {{Z|Z45510}} * {{Z|Z45515}} * {{Z|Z45517}} * {{Z|Z45527}} * {{Z|Z45549}} * {{Z|Z45575}} * {{Z|Z45588}} * {{Z|Z45590}} * {{Z|Z45605}} * {{Z|Z45612}} * {{Z|Z45617}} * {{Z|Z45644}} * {{Z|Z45648}} * {{Z|Z45663}} * {{Z|Z45702}} * {{Z|Z45723}} * {{Z|Z45739}} * {{Z|Z45751}} * {{Z|Z45763}} * {{Z|Z45775}} * {{Z|Z45776}} * {{Z|Z45777}} * {{Z|Z45778}} * {{Z|Z45779}} * {{Z|Z45780}} * {{Z|Z45781}} * {{Z|Z45782}} * {{Z|Z45783}} * {{Z|Z45784}} * {{Z|Z45785}} * {{Z|Z45786}} * {{Z|Z45787}} * {{Z|Z45788}} * {{Z|Z45790}} * {{Z|Z45792}} * {{Z|Z45793}} * {{Z|Z45795}} * {{Z|Z45796}} * {{Z|Z45798}} * {{Z|Z45799}} * {{Z|Z45836}} * {{Z|Z45943}} * {{Z|Z45955}} * {{Z|Z45981}} * {{Z|Z45982}} * {{Z|Z45983}} * {{Z|Z45984}} * {{Z|Z45985}} * {{Z|Z45986}} * {{Z|Z45987}} * {{Z|Z45988}} * {{Z|Z45990}} * {{Z|Z45992}} * {{Z|Z45994}} * {{Z|Z45995}} * {{Z|Z45996}} * {{Z|Z46058}} * {{Z|Z46069}} * {{Z|Z46070}} * {{Z|Z46071}} * {{Z|Z46072}} * {{Z|Z46073}} * {{Z|Z46074}} * {{Z|Z46075}} * {{Z|Z46076}} * {{Z|Z46077}} * {{Z|Z46078}} * {{Z|Z46079}} * {{Z|Z46096}} * {{Z|Z46118}} * {{Z|Z46130}} * {{Z|Z46140}} * {{Z|Z46150}} * {{Z|Z46162}} * {{Z|Z46171}} * {{Z|Z46205}} * {{Z|Z46243}} * {{Z|Z46291}} * {{Z|Z46292}} * {{Z|Z46311}} * {{Z|Z46322}} * {{Z|Z46323}} * {{Z|Z46324}} * {{Z|Z46325}} * {{Z|Z46365}} * {{Z|Z46391}} * {{Z|Z46392}} * {{Z|Z46393}} * {{Z|Z46394}} * {{Z|Z46395}} * {{Z|Z46420}} * {{Z|Z46432}} * {{Z|Z46448}} * {{Z|Z46460}} * {{Z|Z46499}} * {{Z|Z46508}} * {{Z|Z46509}} * {{Z|Z46532}} * {{Z|Z46535}} * {{Z|Z46536}} * {{Z|Z46558}} * {{Z|Z46561}} * {{Z|Z46568}} * {{Z|Z46569}} * {{Z|Z46570}} * {{Z|Z46602}} * {{Z|Z46616}} * {{Z|Z46617}} * {{Z|Z46641}} * {{Z|Z46657}} * {{Z|Z46658}} * {{Z|Z46659}} * {{Z|Z46673}} * {{Z|Z46685}} <span lang="en" dir="ltr" class="mw-content-ltr">A [https://www.wikifunctions.org/wiki/Special:ListObjectsByType?type=Z8&orderby=latest complete list of all functions sorted by when they were created] is available.</span> [[Category:Status updates{{#translation:}}|2026-10-25]] t0cbib0n9de8sqj4dhfmryd72g2tlt7 333920 333918 2026-10-27T19:06:12Z Ameisenigel 44 Created page with "''“Wikiabstrak ist ein offenes Experiment, das strukturierte Daten aus Wikidata in lesbare Zusammenfassungen umwandelt, ganz ohne Sprachmodell (LLM). Sucht man nach einem Land, einem Ort, einer Person oder einem Gebäude, erstellt das System anhand fester Regeln einen Textabschnitt aus Wikidata-Aussagen, sodass sich jeder Satz auf seine Quelle zurückführen lässt.''" 333920 wikitext text/x-wiki <languages/> {{Wikifunctions updates | prevlabel = Vorheriges Update | prev = 2026-10-17 | nextlabel = Nächstes Update | next = }} <span id="Wikiabstrak_app"></span> === Wikiabstrak-App === [[File:Screenshot of Wikiabstrak App.png|thumb|Wikiabstrak App]] Eine neue App wurde von [[:meta:User:Affandy Murad|Affandy Murad]], einem Freiwilligen in der indonesischen Wikipedia und anderen Projekten, entwickelt: [https://wikiabstrak.web.app/ Wikiabstrak]. Die App selbst beschreibt sich wie folgt: ''“Wikiabstrak ist ein offenes Experiment, das strukturierte Daten aus Wikidata in lesbare Zusammenfassungen umwandelt, ganz ohne Sprachmodell (LLM). Sucht man nach einem Land, einem Ort, einer Person oder einem Gebäude, erstellt das System anhand fester Regeln einen Textabschnitt aus Wikidata-Aussagen, sodass sich jeder Satz auf seine Quelle zurückführen lässt.'' <div lang="en" dir="ltr" class="mw-content-ltr"> ''“It also shows key facts, photos from Wikimedia Commons, links to every Wikimedia project, and a ready-made lead-paragraph recipe for Abstract Wikipedia, so you can start or edit language-independent articles.”'' </div> <div lang="en" dir="ltr" class="mw-content-ltr"> Enjoy using the app! If you have suggestions, you can reach Affandy in project telegram / IRC chat, or on [[:meta:User talk:Affandy Murad|his user talk page]]. Also check out the other apps that Affandy has created and that are listed on [[:meta:User:Affandy Murad|his userpage]]. </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === No changes in the software this week === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> Due to the [[:en:PHP2Shell|PHP vulnerabilities]] published this week, we decided to skip deployment beyond safety critical changes. </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === Recording of October Volunteer’s Corner === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> This month’s volunteers’ corner meeting (12 October 2026) is [[:commons:File:Abstract Wikipedia Volunteer Corner 2026-10.webm|now available as a recording on Commons]]. Thank you for the lively discussion and new ideas! </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === Next Volunteers’ Corner on November 9 at 11 UTC === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> The next Volunteers’ Corner will be on [https://zonestamp.toolforge.org/1794222000 Monday, 9 November 2026 at 11:00 UTC]. Note the earlier time in the day, in order to make it easier for some folks to attend this one. We plan to have the following agenda: there will be time to ask questions and discuss all matters arising. If we have time, we will write a function together. Everyone is welcome to join us on [https://meet.google.com/xuy-njxh-rkw Google Meet]. </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === Fresh Functions weekly: 169 new Functions === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> This week we had 169 new functions. Here is an incomplete list of functions with implementations and passing tests to get a taste of what functions have been created. Thanks everybody for contributing! </div> * {{Z|Z45336}} * {{Z|Z45338}} * {{Z|Z45343}} * {{Z|Z45347}} * {{Z|Z45350}} * {{Z|Z45353}} * {{Z|Z45356}} * {{Z|Z45370}} * {{Z|Z45381}} * {{Z|Z45387}} * {{Z|Z45390}} * {{Z|Z45392}} * {{Z|Z45400}} * {{Z|Z45402}} * {{Z|Z45406}} * {{Z|Z45408}} * {{Z|Z45410}} * {{Z|Z45413}} * {{Z|Z45415}} * {{Z|Z45417}} * {{Z|Z45420}} * {{Z|Z45422}} * {{Z|Z45424}} * {{Z|Z45429}} * {{Z|Z45431}} * {{Z|Z45434}} * {{Z|Z45456}} * {{Z|Z45457}} * {{Z|Z45481}} * {{Z|Z45485}} * {{Z|Z45491}} * {{Z|Z45495}} * {{Z|Z45510}} * {{Z|Z45515}} * {{Z|Z45517}} * {{Z|Z45527}} * {{Z|Z45549}} * {{Z|Z45575}} * {{Z|Z45588}} * {{Z|Z45590}} * {{Z|Z45605}} * {{Z|Z45612}} * {{Z|Z45617}} * {{Z|Z45644}} * {{Z|Z45648}} * {{Z|Z45663}} * {{Z|Z45702}} * {{Z|Z45723}} * {{Z|Z45739}} * {{Z|Z45751}} * {{Z|Z45763}} * {{Z|Z45775}} * {{Z|Z45776}} * {{Z|Z45777}} * {{Z|Z45778}} * {{Z|Z45779}} * {{Z|Z45780}} * {{Z|Z45781}} * {{Z|Z45782}} * {{Z|Z45783}} * {{Z|Z45784}} * {{Z|Z45785}} * {{Z|Z45786}} * {{Z|Z45787}} * {{Z|Z45788}} * {{Z|Z45790}} * {{Z|Z45792}} * {{Z|Z45793}} * {{Z|Z45795}} * {{Z|Z45796}} * {{Z|Z45798}} * {{Z|Z45799}} * {{Z|Z45836}} * {{Z|Z45943}} * {{Z|Z45955}} * {{Z|Z45981}} * {{Z|Z45982}} * {{Z|Z45983}} * {{Z|Z45984}} * {{Z|Z45985}} * {{Z|Z45986}} * {{Z|Z45987}} * {{Z|Z45988}} * {{Z|Z45990}} * {{Z|Z45992}} * {{Z|Z45994}} * {{Z|Z45995}} * {{Z|Z45996}} * {{Z|Z46058}} * {{Z|Z46069}} * {{Z|Z46070}} * {{Z|Z46071}} * {{Z|Z46072}} * {{Z|Z46073}} * {{Z|Z46074}} * {{Z|Z46075}} * {{Z|Z46076}} * {{Z|Z46077}} * {{Z|Z46078}} * {{Z|Z46079}} * {{Z|Z46096}} * {{Z|Z46118}} * {{Z|Z46130}} * {{Z|Z46140}} * {{Z|Z46150}} * {{Z|Z46162}} * {{Z|Z46171}} * {{Z|Z46205}} * {{Z|Z46243}} * {{Z|Z46291}} * {{Z|Z46292}} * {{Z|Z46311}} * {{Z|Z46322}} * {{Z|Z46323}} * {{Z|Z46324}} * {{Z|Z46325}} * {{Z|Z46365}} * {{Z|Z46391}} * {{Z|Z46392}} * {{Z|Z46393}} * {{Z|Z46394}} * {{Z|Z46395}} * {{Z|Z46420}} * {{Z|Z46432}} * {{Z|Z46448}} * {{Z|Z46460}} * {{Z|Z46499}} * {{Z|Z46508}} * {{Z|Z46509}} * {{Z|Z46532}} * {{Z|Z46535}} * {{Z|Z46536}} * {{Z|Z46558}} * {{Z|Z46561}} * {{Z|Z46568}} * {{Z|Z46569}} * {{Z|Z46570}} * {{Z|Z46602}} * {{Z|Z46616}} * {{Z|Z46617}} * {{Z|Z46641}} * {{Z|Z46657}} * {{Z|Z46658}} * {{Z|Z46659}} * {{Z|Z46673}} * {{Z|Z46685}} <span lang="en" dir="ltr" class="mw-content-ltr">A [https://www.wikifunctions.org/wiki/Special:ListObjectsByType?type=Z8&orderby=latest complete list of all functions sorted by when they were created] is available.</span> [[Category:Status updates{{#translation:}}|2026-10-25]] d19vfwmljm8wydo6yb877mppfye99cg 333922 333920 2026-10-27T19:08:34Z Ameisenigel 44 Created page with "''“Zudem werden wichtige Fakten, Fotos von Wikimedia Commons sowie Links zu sämtlichen Wikimedia-Projekten angezeigt und es gibt eine vorgefertigte Vorlage für den Einleitungsabsatz für die Abstrakte Wikipedia, die es dir ermöglicht, sprachunabhängige Artikel zu erstellen oder zu bearbeiten.”''" 333922 wikitext text/x-wiki <languages/> {{Wikifunctions updates | prevlabel = Vorheriges Update | prev = 2026-10-17 | nextlabel = Nächstes Update | next = }} <span id="Wikiabstrak_app"></span> === Wikiabstrak-App === [[File:Screenshot of Wikiabstrak App.png|thumb|Wikiabstrak App]] Eine neue App wurde von [[:meta:User:Affandy Murad|Affandy Murad]], einem Freiwilligen in der indonesischen Wikipedia und anderen Projekten, entwickelt: [https://wikiabstrak.web.app/ Wikiabstrak]. Die App selbst beschreibt sich wie folgt: ''“Wikiabstrak ist ein offenes Experiment, das strukturierte Daten aus Wikidata in lesbare Zusammenfassungen umwandelt, ganz ohne Sprachmodell (LLM). Sucht man nach einem Land, einem Ort, einer Person oder einem Gebäude, erstellt das System anhand fester Regeln einen Textabschnitt aus Wikidata-Aussagen, sodass sich jeder Satz auf seine Quelle zurückführen lässt.'' ''“Zudem werden wichtige Fakten, Fotos von Wikimedia Commons sowie Links zu sämtlichen Wikimedia-Projekten angezeigt und es gibt eine vorgefertigte Vorlage für den Einleitungsabsatz für die Abstrakte Wikipedia, die es dir ermöglicht, sprachunabhängige Artikel zu erstellen oder zu bearbeiten.”'' <div lang="en" dir="ltr" class="mw-content-ltr"> Enjoy using the app! If you have suggestions, you can reach Affandy in project telegram / IRC chat, or on [[:meta:User talk:Affandy Murad|his user talk page]]. Also check out the other apps that Affandy has created and that are listed on [[:meta:User:Affandy Murad|his userpage]]. </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === No changes in the software this week === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> Due to the [[:en:PHP2Shell|PHP vulnerabilities]] published this week, we decided to skip deployment beyond safety critical changes. </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === Recording of October Volunteer’s Corner === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> This month’s volunteers’ corner meeting (12 October 2026) is [[:commons:File:Abstract Wikipedia Volunteer Corner 2026-10.webm|now available as a recording on Commons]]. Thank you for the lively discussion and new ideas! </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === Next Volunteers’ Corner on November 9 at 11 UTC === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> The next Volunteers’ Corner will be on [https://zonestamp.toolforge.org/1794222000 Monday, 9 November 2026 at 11:00 UTC]. Note the earlier time in the day, in order to make it easier for some folks to attend this one. We plan to have the following agenda: there will be time to ask questions and discuss all matters arising. If we have time, we will write a function together. Everyone is welcome to join us on [https://meet.google.com/xuy-njxh-rkw Google Meet]. </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === Fresh Functions weekly: 169 new Functions === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> This week we had 169 new functions. Here is an incomplete list of functions with implementations and passing tests to get a taste of what functions have been created. Thanks everybody for contributing! </div> * {{Z|Z45336}} * {{Z|Z45338}} * {{Z|Z45343}} * {{Z|Z45347}} * {{Z|Z45350}} * {{Z|Z45353}} * {{Z|Z45356}} * {{Z|Z45370}} * {{Z|Z45381}} * {{Z|Z45387}} * {{Z|Z45390}} * {{Z|Z45392}} * {{Z|Z45400}} * {{Z|Z45402}} * {{Z|Z45406}} * {{Z|Z45408}} * {{Z|Z45410}} * {{Z|Z45413}} * {{Z|Z45415}} * {{Z|Z45417}} * {{Z|Z45420}} * {{Z|Z45422}} * {{Z|Z45424}} * {{Z|Z45429}} * {{Z|Z45431}} * {{Z|Z45434}} * {{Z|Z45456}} * {{Z|Z45457}} * {{Z|Z45481}} * {{Z|Z45485}} * {{Z|Z45491}} * {{Z|Z45495}} * {{Z|Z45510}} * {{Z|Z45515}} * {{Z|Z45517}} * {{Z|Z45527}} * {{Z|Z45549}} * {{Z|Z45575}} * {{Z|Z45588}} * {{Z|Z45590}} * {{Z|Z45605}} * {{Z|Z45612}} * {{Z|Z45617}} * {{Z|Z45644}} * {{Z|Z45648}} * {{Z|Z45663}} * {{Z|Z45702}} * {{Z|Z45723}} * {{Z|Z45739}} * {{Z|Z45751}} * {{Z|Z45763}} * {{Z|Z45775}} * {{Z|Z45776}} * {{Z|Z45777}} * {{Z|Z45778}} * {{Z|Z45779}} * {{Z|Z45780}} * {{Z|Z45781}} * {{Z|Z45782}} * {{Z|Z45783}} * {{Z|Z45784}} * {{Z|Z45785}} * {{Z|Z45786}} * {{Z|Z45787}} * {{Z|Z45788}} * {{Z|Z45790}} * {{Z|Z45792}} * {{Z|Z45793}} * {{Z|Z45795}} * {{Z|Z45796}} * {{Z|Z45798}} * {{Z|Z45799}} * {{Z|Z45836}} * {{Z|Z45943}} * {{Z|Z45955}} * {{Z|Z45981}} * {{Z|Z45982}} * {{Z|Z45983}} * {{Z|Z45984}} * {{Z|Z45985}} * {{Z|Z45986}} * {{Z|Z45987}} * {{Z|Z45988}} * {{Z|Z45990}} * {{Z|Z45992}} * {{Z|Z45994}} * {{Z|Z45995}} * {{Z|Z45996}} * {{Z|Z46058}} * {{Z|Z46069}} * {{Z|Z46070}} * {{Z|Z46071}} * {{Z|Z46072}} * {{Z|Z46073}} * {{Z|Z46074}} * {{Z|Z46075}} * {{Z|Z46076}} * {{Z|Z46077}} * {{Z|Z46078}} * {{Z|Z46079}} * {{Z|Z46096}} * {{Z|Z46118}} * {{Z|Z46130}} * {{Z|Z46140}} * {{Z|Z46150}} * {{Z|Z46162}} * {{Z|Z46171}} * {{Z|Z46205}} * {{Z|Z46243}} * {{Z|Z46291}} * {{Z|Z46292}} * {{Z|Z46311}} * {{Z|Z46322}} * {{Z|Z46323}} * {{Z|Z46324}} * {{Z|Z46325}} * {{Z|Z46365}} * {{Z|Z46391}} * {{Z|Z46392}} * {{Z|Z46393}} * {{Z|Z46394}} * {{Z|Z46395}} * {{Z|Z46420}} * {{Z|Z46432}} * {{Z|Z46448}} * {{Z|Z46460}} * {{Z|Z46499}} * {{Z|Z46508}} * {{Z|Z46509}} * {{Z|Z46532}} * {{Z|Z46535}} * {{Z|Z46536}} * {{Z|Z46558}} * {{Z|Z46561}} * {{Z|Z46568}} * {{Z|Z46569}} * {{Z|Z46570}} * {{Z|Z46602}} * {{Z|Z46616}} * {{Z|Z46617}} * {{Z|Z46641}} * {{Z|Z46657}} * {{Z|Z46658}} * {{Z|Z46659}} * {{Z|Z46673}} * {{Z|Z46685}} <span lang="en" dir="ltr" class="mw-content-ltr">A [https://www.wikifunctions.org/wiki/Special:ListObjectsByType?type=Z8&orderby=latest complete list of all functions sorted by when they were created] is available.</span> [[Category:Status updates{{#translation:}}|2026-10-25]] hdfjfuambmullft3vddftc5o6w67b4g 333924 333922 2026-10-27T19:12:33Z Ameisenigel 44 Created page with "Viel Spaß bei der Nutzung der App! Falls du Vorschläge hast, kannst du Affandy im Telegram-/IRC-Chat des Projekts oder auf [[$1|seiner Benutzerdiskussionsseite]] kontaktieren. Schau dir auch die weiteren Apps an, die Affandy entwickelt hat und die auf [[$2|seiner Benutzerseite]] aufgelistet sind." 333924 wikitext text/x-wiki <languages/> {{Wikifunctions updates | prevlabel = Vorheriges Update | prev = 2026-10-17 | nextlabel = Nächstes Update | next = }} <span id="Wikiabstrak_app"></span> === Wikiabstrak-App === [[File:Screenshot of Wikiabstrak App.png|thumb|Wikiabstrak App]] Eine neue App wurde von [[:meta:User:Affandy Murad|Affandy Murad]], einem Freiwilligen in der indonesischen Wikipedia und anderen Projekten, entwickelt: [https://wikiabstrak.web.app/ Wikiabstrak]. Die App selbst beschreibt sich wie folgt: ''“Wikiabstrak ist ein offenes Experiment, das strukturierte Daten aus Wikidata in lesbare Zusammenfassungen umwandelt, ganz ohne Sprachmodell (LLM). Sucht man nach einem Land, einem Ort, einer Person oder einem Gebäude, erstellt das System anhand fester Regeln einen Textabschnitt aus Wikidata-Aussagen, sodass sich jeder Satz auf seine Quelle zurückführen lässt.'' ''“Zudem werden wichtige Fakten, Fotos von Wikimedia Commons sowie Links zu sämtlichen Wikimedia-Projekten angezeigt und es gibt eine vorgefertigte Vorlage für den Einleitungsabsatz für die Abstrakte Wikipedia, die es dir ermöglicht, sprachunabhängige Artikel zu erstellen oder zu bearbeiten.”'' Viel Spaß bei der Nutzung der App! Falls du Vorschläge hast, kannst du Affandy im Telegram-/IRC-Chat des Projekts oder auf [[:meta:User talk:Affandy Murad|seiner Benutzerdiskussionsseite]] kontaktieren. Schau dir auch die weiteren Apps an, die Affandy entwickelt hat und die auf [[:meta:User:Affandy Murad|seiner Benutzerseite]] aufgelistet sind. <div lang="en" dir="ltr" class="mw-content-ltr"> === No changes in the software this week === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> Due to the [[:en:PHP2Shell|PHP vulnerabilities]] published this week, we decided to skip deployment beyond safety critical changes. </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === Recording of October Volunteer’s Corner === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> This month’s volunteers’ corner meeting (12 October 2026) is [[:commons:File:Abstract Wikipedia Volunteer Corner 2026-10.webm|now available as a recording on Commons]]. Thank you for the lively discussion and new ideas! </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === Next Volunteers’ Corner on November 9 at 11 UTC === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> The next Volunteers’ Corner will be on [https://zonestamp.toolforge.org/1794222000 Monday, 9 November 2026 at 11:00 UTC]. Note the earlier time in the day, in order to make it easier for some folks to attend this one. We plan to have the following agenda: there will be time to ask questions and discuss all matters arising. If we have time, we will write a function together. Everyone is welcome to join us on [https://meet.google.com/xuy-njxh-rkw Google Meet]. </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === Fresh Functions weekly: 169 new Functions === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> This week we had 169 new functions. Here is an incomplete list of functions with implementations and passing tests to get a taste of what functions have been created. Thanks everybody for contributing! </div> * {{Z|Z45336}} * {{Z|Z45338}} * {{Z|Z45343}} * {{Z|Z45347}} * {{Z|Z45350}} * {{Z|Z45353}} * {{Z|Z45356}} * {{Z|Z45370}} * {{Z|Z45381}} * {{Z|Z45387}} * {{Z|Z45390}} * {{Z|Z45392}} * {{Z|Z45400}} * {{Z|Z45402}} * {{Z|Z45406}} * {{Z|Z45408}} * {{Z|Z45410}} * {{Z|Z45413}} * {{Z|Z45415}} * {{Z|Z45417}} * {{Z|Z45420}} * {{Z|Z45422}} * {{Z|Z45424}} * {{Z|Z45429}} * {{Z|Z45431}} * {{Z|Z45434}} * {{Z|Z45456}} * {{Z|Z45457}} * {{Z|Z45481}} * {{Z|Z45485}} * {{Z|Z45491}} * {{Z|Z45495}} * {{Z|Z45510}} * {{Z|Z45515}} * {{Z|Z45517}} * {{Z|Z45527}} * {{Z|Z45549}} * {{Z|Z45575}} * {{Z|Z45588}} * {{Z|Z45590}} * {{Z|Z45605}} * {{Z|Z45612}} * {{Z|Z45617}} * {{Z|Z45644}} * {{Z|Z45648}} * {{Z|Z45663}} * {{Z|Z45702}} * {{Z|Z45723}} * {{Z|Z45739}} * {{Z|Z45751}} * {{Z|Z45763}} * {{Z|Z45775}} * {{Z|Z45776}} * {{Z|Z45777}} * {{Z|Z45778}} * {{Z|Z45779}} * {{Z|Z45780}} * {{Z|Z45781}} * {{Z|Z45782}} * {{Z|Z45783}} * {{Z|Z45784}} * {{Z|Z45785}} * {{Z|Z45786}} * {{Z|Z45787}} * {{Z|Z45788}} * {{Z|Z45790}} * {{Z|Z45792}} * {{Z|Z45793}} * {{Z|Z45795}} * {{Z|Z45796}} * {{Z|Z45798}} * {{Z|Z45799}} * {{Z|Z45836}} * {{Z|Z45943}} * {{Z|Z45955}} * {{Z|Z45981}} * {{Z|Z45982}} * {{Z|Z45983}} * {{Z|Z45984}} * {{Z|Z45985}} * {{Z|Z45986}} * {{Z|Z45987}} * {{Z|Z45988}} * {{Z|Z45990}} * {{Z|Z45992}} * {{Z|Z45994}} * {{Z|Z45995}} * {{Z|Z45996}} * {{Z|Z46058}} * {{Z|Z46069}} * {{Z|Z46070}} * {{Z|Z46071}} * {{Z|Z46072}} * {{Z|Z46073}} * {{Z|Z46074}} * {{Z|Z46075}} * {{Z|Z46076}} * {{Z|Z46077}} * {{Z|Z46078}} * {{Z|Z46079}} * {{Z|Z46096}} * {{Z|Z46118}} * {{Z|Z46130}} * {{Z|Z46140}} * {{Z|Z46150}} * {{Z|Z46162}} * {{Z|Z46171}} * {{Z|Z46205}} * {{Z|Z46243}} * {{Z|Z46291}} * {{Z|Z46292}} * {{Z|Z46311}} * {{Z|Z46322}} * {{Z|Z46323}} * {{Z|Z46324}} * {{Z|Z46325}} * {{Z|Z46365}} * {{Z|Z46391}} * {{Z|Z46392}} * {{Z|Z46393}} * {{Z|Z46394}} * {{Z|Z46395}} * {{Z|Z46420}} * {{Z|Z46432}} * {{Z|Z46448}} * {{Z|Z46460}} * {{Z|Z46499}} * {{Z|Z46508}} * {{Z|Z46509}} * {{Z|Z46532}} * {{Z|Z46535}} * {{Z|Z46536}} * {{Z|Z46558}} * {{Z|Z46561}} * {{Z|Z46568}} * {{Z|Z46569}} * {{Z|Z46570}} * {{Z|Z46602}} * {{Z|Z46616}} * {{Z|Z46617}} * {{Z|Z46641}} * {{Z|Z46657}} * {{Z|Z46658}} * {{Z|Z46659}} * {{Z|Z46673}} * {{Z|Z46685}} <span lang="en" dir="ltr" class="mw-content-ltr">A [https://www.wikifunctions.org/wiki/Special:ListObjectsByType?type=Z8&orderby=latest complete list of all functions sorted by when they were created] is available.</span> [[Category:Status updates{{#translation:}}|2026-10-25]] isv8n5fybrwu513hgzcuiazpca2eh56 333926 333924 2026-10-27T19:13:00Z Ameisenigel 44 Created page with "=== Keine Änderungen an der Software in dieser Woche ===" 333926 wikitext text/x-wiki <languages/> {{Wikifunctions updates | prevlabel = Vorheriges Update | prev = 2026-10-17 | nextlabel = Nächstes Update | next = }} <span id="Wikiabstrak_app"></span> === Wikiabstrak-App === [[File:Screenshot of Wikiabstrak App.png|thumb|Wikiabstrak App]] Eine neue App wurde von [[:meta:User:Affandy Murad|Affandy Murad]], einem Freiwilligen in der indonesischen Wikipedia und anderen Projekten, entwickelt: [https://wikiabstrak.web.app/ Wikiabstrak]. Die App selbst beschreibt sich wie folgt: ''“Wikiabstrak ist ein offenes Experiment, das strukturierte Daten aus Wikidata in lesbare Zusammenfassungen umwandelt, ganz ohne Sprachmodell (LLM). Sucht man nach einem Land, einem Ort, einer Person oder einem Gebäude, erstellt das System anhand fester Regeln einen Textabschnitt aus Wikidata-Aussagen, sodass sich jeder Satz auf seine Quelle zurückführen lässt.'' ''“Zudem werden wichtige Fakten, Fotos von Wikimedia Commons sowie Links zu sämtlichen Wikimedia-Projekten angezeigt und es gibt eine vorgefertigte Vorlage für den Einleitungsabsatz für die Abstrakte Wikipedia, die es dir ermöglicht, sprachunabhängige Artikel zu erstellen oder zu bearbeiten.”'' Viel Spaß bei der Nutzung der App! Falls du Vorschläge hast, kannst du Affandy im Telegram-/IRC-Chat des Projekts oder auf [[:meta:User talk:Affandy Murad|seiner Benutzerdiskussionsseite]] kontaktieren. Schau dir auch die weiteren Apps an, die Affandy entwickelt hat und die auf [[:meta:User:Affandy Murad|seiner Benutzerseite]] aufgelistet sind. <span id="No_changes_in_the_software_this_week"></span> === Keine Änderungen an der Software in dieser Woche === <div lang="en" dir="ltr" class="mw-content-ltr"> Due to the [[:en:PHP2Shell|PHP vulnerabilities]] published this week, we decided to skip deployment beyond safety critical changes. </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === Recording of October Volunteer’s Corner === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> This month’s volunteers’ corner meeting (12 October 2026) is [[:commons:File:Abstract Wikipedia Volunteer Corner 2026-10.webm|now available as a recording on Commons]]. Thank you for the lively discussion and new ideas! </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === Next Volunteers’ Corner on November 9 at 11 UTC === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> The next Volunteers’ Corner will be on [https://zonestamp.toolforge.org/1794222000 Monday, 9 November 2026 at 11:00 UTC]. Note the earlier time in the day, in order to make it easier for some folks to attend this one. We plan to have the following agenda: there will be time to ask questions and discuss all matters arising. If we have time, we will write a function together. Everyone is welcome to join us on [https://meet.google.com/xuy-njxh-rkw Google Meet]. </div> <div lang="en" dir="ltr" class="mw-content-ltr"> === Fresh Functions weekly: 169 new Functions === </div> <div lang="en" dir="ltr" class="mw-content-ltr"> This week we had 169 new functions. Here is an incomplete list of functions with implementations and passing tests to get a taste of what functions have been created. Thanks everybody for contributing! </div> * {{Z|Z45336}} * {{Z|Z45338}} * {{Z|Z45343}} * {{Z|Z45347}} * {{Z|Z45350}} * {{Z|Z45353}} * {{Z|Z45356}} * {{Z|Z45370}} * {{Z|Z45381}} * {{Z|Z45387}} * {{Z|Z45390}} * {{Z|Z45392}} * {{Z|Z45400}} * {{Z|Z45402}} * {{Z|Z45406}} * {{Z|Z45408}} * {{Z|Z45410}} * {{Z|Z45413}} * {{Z|Z45415}} * {{Z|Z45417}} * {{Z|Z45420}} * {{Z|Z45422}} * {{Z|Z45424}} * {{Z|Z45429}} * {{Z|Z45431}} * {{Z|Z45434}} * {{Z|Z45456}} * {{Z|Z45457}} * {{Z|Z45481}} * {{Z|Z45485}} * {{Z|Z45491}} * {{Z|Z45495}} * {{Z|Z45510}} * {{Z|Z45515}} * {{Z|Z45517}} * {{Z|Z45527}} * {{Z|Z45549}} * {{Z|Z45575}} * {{Z|Z45588}} * {{Z|Z45590}} * {{Z|Z45605}} * {{Z|Z45612}} * {{Z|Z45617}} * {{Z|Z45644}} * {{Z|Z45648}} * {{Z|Z45663}} * {{Z|Z45702}} * {{Z|Z45723}} * {{Z|Z45739}} * {{Z|Z45751}} * {{Z|Z45763}} * {{Z|Z45775}} * {{Z|Z45776}} * {{Z|Z45777}} * {{Z|Z45778}} * {{Z|Z45779}} * {{Z|Z45780}} * {{Z|Z45781}} * {{Z|Z45782}} * {{Z|Z45783}} * {{Z|Z45784}} * {{Z|Z45785}} * {{Z|Z45786}} * {{Z|Z45787}} * {{Z|Z45788}} * {{Z|Z45790}} * {{Z|Z45792}} * {{Z|Z45793}} * {{Z|Z45795}} * {{Z|Z45796}} * {{Z|Z45798}} * {{Z|Z45799}} * {{Z|Z45836}} * {{Z|Z45943}} * {{Z|Z45955}} * {{Z|Z45981}} * {{Z|Z45982}} * {{Z|Z45983}} * {{Z|Z45984}} * {{Z|Z45985}} * {{Z|Z45986}} * {{Z|Z45987}} * {{Z|Z45988}} * {{Z|Z45990}} * {{Z|Z45992}} * {{Z|Z45994}} * {{Z|Z45995}} * {{Z|Z45996}} * {{Z|Z46058}} * {{Z|Z46069}} * {{Z|Z46070}} * {{Z|Z46071}} * {{Z|Z46072}} * {{Z|Z46073}} * {{Z|Z46074}} * {{Z|Z46075}} * {{Z|Z46076}} * {{Z|Z46077}} * {{Z|Z46078}} * {{Z|Z46079}} * {{Z|Z46096}} * {{Z|Z46118}} * {{Z|Z46130}} * {{Z|Z46140}} * {{Z|Z46150}} * {{Z|Z46162}} * {{Z|Z46171}} * {{Z|Z46205}} * {{Z|Z46243}} * {{Z|Z46291}} * {{Z|Z46292}} * {{Z|Z46311}} * {{Z|Z46322}} * {{Z|Z46323}} * {{Z|Z46324}} * {{Z|Z46325}} * {{Z|Z46365}} * {{Z|Z46391}} * {{Z|Z46392}} * {{Z|Z46393}} * {{Z|Z46394}} * {{Z|Z46395}} * {{Z|Z46420}} * {{Z|Z46432}} * {{Z|Z46448}} * {{Z|Z46460}} * {{Z|Z46499}} * {{Z|Z46508}} * {{Z|Z46509}} * {{Z|Z46532}} * {{Z|Z46535}} * {{Z|Z46536}} * {{Z|Z46558}} * {{Z|Z46561}} * {{Z|Z46568}} * {{Z|Z46569}} * {{Z|Z46570}} * {{Z|Z46602}} * {{Z|Z46616}} * {{Z|Z46617}} * {{Z|Z46641}} * {{Z|Z46657}} * {{Z|Z46658}} * {{Z|Z46659}} * {{Z|Z46673}} * {{Z|Z46685}} <span lang="en" dir="ltr" class="mw-content-ltr">A [https://www.wikifunctions.org/wiki/Special:ListObjectsByType?type=Z8&orderby=latest complete list of all functions sorted by when they were created] is available.</span> [[Category:Status updates{{#translation:}}|2026-10-25]] lozraitrzx95yz36n4o43smewjg6ukm Z47813 0 101492 333891 333516 2026-10-27T12:20:43Z HenkvD 1290 English label 333891 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47813" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47808", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z47808", "Z47808K1": { "Z1K1": "Z6091", "Z6091K1": "Q29378617" }, "Z47808K2": { "Z1K1": "Z40", "Z40K1": "Z41" }, "Z47808K3": { "Z1K1": "Z6091", "Z6091K1": "Q192613" }, "Z47808K4": "Z1430" }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z14392", "Z14392K2": { "Z1K1": "Z11", "Z11K1": { "Z1K1": "Z60", "Z60K1": "de" }, "Z11K2": "Die zentralen Themen von 120 BPM sind LGBTQ-Rechte, Lesben- und Schwulenbewegung, Act Up, HIV/AIDS in Frankreichund LGBT-Rechte in Frankreich." } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1430", "Z11K2": "Zentralen Theman 120 BPM" }, { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "BPM (Beats per Minute) main subject" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } g8fz2wttpzmvyligeulx1gg5mssrvaz Z47861 0 101544 333893 333869 2026-10-27T14:04:45Z Satdeep Gill 10395 Added Z47862 to the approved list of implementations 333893 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47861" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6", "Z17K2": "Z47861K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "text" } ] } } ], "Z8K2": "Z6", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14", "Z47862" ], "Z8K5": "Z47861" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "format plural class label (English)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } hy4xps8qag8qnc2vb5fasy69fomhuvw Z47862 0 101545 333892 333868 2026-10-27T14:02:44Z Satdeep Gill 10395 333892 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47862" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z47861", "Z14K3": { "Z1K1": "Z16", "Z16K1": "Z610", "Z16K2": "def Z47861(Z47861K1):\n\ttext = Z47861K1\n\tif not text:\n\t\treturn \"\"\n\n\tt_lower = text.lower().strip()\n\n\t# Strip leading indefinite article for uniform checking\n\traw = t_lower[2:] if t_lower.startswith(\"a \") else (t_lower[3:] if t_lower.startswith(\"an \") else t_lower)\n\n\t# Common collective/partitive heads\n\tcollective_heads = {\n\t\t\"group\", \"chain\", \"range\", \"cluster\", \"collection\", \"series\",\n\t\t\"set\", \"system\", \"pair\", \"flock\", \"herd\", \"pack\", \"archipelago\",\n\t\t\"network\", \"band\", \"swarm\", \"school\", \"fleet\", \"constellation\",\n\t\t\"array\", \"suite\", \"bundle\", \"clump\", \"bunch\", \"belt\"\n\t}\n\n\t# Check for \"[collective_head] of [plural elements]\"\n\tif \" of \" in raw:\n\t\tparts = raw.split(\" of \", 1)\n\t\thead = parts[0].strip()\n\t\ttail = parts[1].strip()\n\n\t\t# If the head is a known collective noun or the complement is already plural\n\t\tif head in collective_heads or tail.endswith(\"s\"):\n\t\t\tarticle = \"an \" if raw[0] in \"aeiou\" else \"a \"\n\t\t\treturn raw if t_lower.startswith((\"a \", \"an \")) else article + raw\n\n\t# Prepositional count phrases with singular mass/count complements (e.g., \"body of water\" -\u003E \"bodies of water\")\n\tif \" of \" in text and \" \" not in text[:text.index(\" of \")].strip():\n\t\tidx = text.index(\" of \")\n\t\thead = text[:idx]\n\t\ttail = text[idx:]\n\t\tif head.lower().endswith(\"y\") and not head.lower().endswith((\"ay\", \"ey\", \"oy\", \"uy\")):\n\t\t\treturn head[:-1] + \"ies\" + tail\n\t\treturn head + \"s\" + tail\n\n\t# Standard plurals for standalone count nouns\n\tif text.endswith((\"s\", \"sh\", \"ch\", \"x\", \"z\")):\n\t\treturn text + \"es\"\n\tif text.endswith(\"y\") and not text.lower().endswith((\"ay\", \"ey\", \"oy\", \"uy\")):\n\t\treturn text[:-1] + \"ies\"\n\treturn text + \"s\"" } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "format plural class label, python" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } ptiuezbnnxptq8a09a2qsrulipt0rfr Z47866 0 101565 333906 333731 2026-10-27T16:26:11Z ReXLer 39813 333906 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47866" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z44598", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z44598", "Z44598K1": { "Z1K1": "Z6091", "Z6091K1": "Q928" }, "Z44598K2": [ "Z6091", { "Z1K1": "Z6091", "Z6091K1": "Q11815167" }, { "Z1K1": "Z6091", "Z6091K1": "Q7270" } ], "Z44598K3": "Z1002" }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z877", "Z877K2": { "Z1K1": "Z89", "Z89K1": "The Philippines is an archipelagic state and a republic." } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "The Philippines is a ...." } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 0p8jghdz3m1f2ixgf2fx2cp5o7jhxqr Z47959 0 101658 333896 333866 2026-10-27T14:08:14Z Satdeep Gill 10395 333896 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47959" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z47958", "Z14K3": { "Z1K1": "Z16", "Z16K1": "Z610", "Z16K2": "def Z47958(Z47958K1):\n entity_label = Z47958K1\n if not entity_label:\n return \"\"\n\n label_lower = entity_label.lower().strip()\n\n # Already starts with \"the\"\n if label_lower.startswith(\"the \"):\n return \"\"\n\n definite_names = {\n \"philippines\", \"netherlands\", \"united states\", \"united kingdom\",\n \"united arab emirates\", \"czech republic\", \"dominican republic\",\n \"bahamas\", \"maldives\", \"seychelles\", \"gambia\", \"vatican city\",\n \"soviet union\", \"bronx\", \"hague\"\n }\n\n if label_lower in definite_names:\n return \"The \"\n\n patterns = (\"republic of\", \"kingdom of\", \"federation of\", \"islands\")\n if any(p in label_lower for p in patterns):\n return \"The \"\n\n return \"\"" } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "determine English definite article for entity,comp" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } jqpbts05o1sruqqaun1t58zigvoq0nz Z47960 0 101659 333870 2026-10-27T12:14:43Z Jsamwrites 938 Create Classification sentence, English: Eiffel Tower 333870 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47960" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47251", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47251", "Z47251K1": { "Z1K1": "Z6091", "Z6091K1": "Q243" }, "Z47251K2": { "Z1K1": "Z60", "Z60K1": "en" }, "Z47251K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "The Eiffel Tower is a landmark." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Classification sentence, English: Eiffel Tower" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 88k5flb4a0vianxf5y3psik0vu4cgp5 Z47961 0 101660 333871 2026-10-27T12:14:45Z Jsamwrites 938 Create Classification sentence, Igbo: Eiffel Tower 333871 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47961" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47251", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47251", "Z47251K1": { "Z1K1": "Z6091", "Z6091K1": "Q243" }, "Z47251K2": { "Z1K1": "Z60", "Z60K1": "ig" }, "Z47251K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "Tour Eiffel bụ ụlọ elu." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Classification sentence, Igbo: Eiffel Tower" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 5ttyn4higuh87pbg9ogjm4k88vkkghg Z47962 0 101661 333872 2026-10-27T12:14:47Z Jsamwrites 938 Create Classification sentence, Dagbani: Eiffel Tower 333872 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47962" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47251", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47251", "Z47251K1": { "Z1K1": "Z6091", "Z6091K1": "Q243" }, "Z47251K2": { "Z1K1": "Z60", "Z60K1": "dag" }, "Z47251K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "Tour Eiffel nyɛla toowa." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Classification sentence, Dagbani: Eiffel Tower" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } ofz9yv8isv2or4x749u1i6x5atjjri5 Z47963 0 101662 333873 2026-10-27T12:14:48Z Jsamwrites 938 Create Founder sentence, Latin: Google 333873 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47963" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z46989", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z46989", "Z46989K1": { "Z1K1": "Z6091", "Z6091K1": "Q95" }, "Z46989K2": { "Z1K1": "Z60", "Z60K1": "la" }, "Z46989K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "Sergius Brin et Laurentius Page Google condiderunt." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Founder sentence, Latin: Google" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } rnlrgkk053ltyrxbrs6pbj644q3rwcu Z47964 0 101663 333874 2026-10-27T12:14:50Z Jsamwrites 938 Create Founder sentence, Dagbani: Google 333874 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47964" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z46989", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z46989", "Z46989K1": { "Z1K1": "Z6091", "Z6091K1": "Q95" }, "Z46989K2": { "Z1K1": "Z60", "Z60K1": "dag" }, "Z46989K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "Sergey Brin mini Larry Page daa kpaɣi Google." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Founder sentence, Dagbani: Google" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } nhq3zl64ilbj2w2e3919s8g48zrj6cj Z47965 0 101664 333875 2026-10-27T12:14:52Z Jsamwrites 938 Create Programming language sentence, French: Inkscape 333875 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47965" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47472", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47472", "Z47472K1": { "Z1K1": "Z6091", "Z6091K1": "Q8041" }, "Z47472K2": { "Z1K1": "Z60", "Z60K1": "fr" }, "Z47472K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "Inkscape est écrit en C++ et C." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Programming language sentence, French: Inkscape" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } q41rwyqrrt1o5xacqgucvlvqdqijfyb Z47966 0 101665 333876 2026-10-27T12:14:54Z Jsamwrites 938 Create Programming language sentence, Spanish: Inkscape 333876 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47966" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47472", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47472", "Z47472K1": { "Z1K1": "Z6091", "Z6091K1": "Q8041" }, "Z47472K2": { "Z1K1": "Z60", "Z60K1": "es" }, "Z47472K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "Inkscape es escrito en C++ y C." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Programming language sentence, Spanish: Inkscape" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } h06ik63l6oqehwzkqqdj0icavetvmqv Z47967 0 101666 333877 2026-10-27T12:14:56Z Jsamwrites 938 Create Programming language sentence, Latin: Inkscape 333877 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47967" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47472", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47472", "Z47472K1": { "Z1K1": "Z6091", "Z6091K1": "Q8041" }, "Z47472K2": { "Z1K1": "Z60", "Z60K1": "la" }, "Z47472K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "Inkscape C++ et C scribitur." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Programming language sentence, Latin: Inkscape" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 1rjift59wtusge1xj8msue2pje5mj2p Z47968 0 101667 333878 2026-10-27T12:14:57Z Jsamwrites 938 Create Programming language sentence, Malayalam: Inkscape 333878 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47968" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47472", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47472", "Z47472K1": { "Z1K1": "Z6091", "Z6091K1": "Q8041" }, "Z47472K2": { "Z1K1": "Z60", "Z60K1": "ml" }, "Z47472K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "ഇങ്ക്‌സ്കേപ്പ് സി++-ലും സിയിലും എഴുതപ്പെടുന്നു." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Programming language sentence, Malayalam: Inkscape" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 1by848gfhpmnfw33m624f1mvlnhd8sj Z47969 0 101668 333879 2026-10-27T12:14:59Z Jsamwrites 938 Create Programming language sentence, Igbo: Inkscape 333879 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47969" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47472", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47472", "Z47472K1": { "Z1K1": "Z6091", "Z6091K1": "Q8041" }, "Z47472K2": { "Z1K1": "Z60", "Z60K1": "ig" }, "Z47472K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "E dere Inkscape na C++ na C." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Programming language sentence, Igbo: Inkscape" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } kt6sp12cpqz1ebop2dfhysnnlx2xu8s Z47970 0 101669 333880 2026-10-27T12:15:01Z Jsamwrites 938 Create Programming language sentence, Dagbani: Inkscape 333880 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47970" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47472", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47472", "Z47472K1": { "Z1K1": "Z6091", "Z6091K1": "Q8041" }, "Z47472K2": { "Z1K1": "Z60", "Z60K1": "dag" }, "Z47472K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "Bɛ sabi Inkscape C++ mini C ni." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Programming language sentence, Dagbani: Inkscape" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } dcalproqbz9shhg1kmg5lzseqknk41x Z47971 0 101670 333881 2026-10-27T12:15:02Z Jsamwrites 938 Create Operating system sentence, French: Inkscape 333881 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47971" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47474", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47474", "Z47474K1": { "Z1K1": "Z6091", "Z6091K1": "Q8041" }, "Z47474K2": { "Z1K1": "Z60", "Z60K1": "fr" }, "Z47474K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "Inkscape fonctionne sous Linux, Microsoft Windows et d'autres." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Operating system sentence, French: Inkscape" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } rlm06k6wbfdt1zw9j0uidy8qggm497e Z47972 0 101671 333882 2026-10-27T12:15:04Z Jsamwrites 938 Create Operating system sentence, Spanish: Inkscape 333882 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47972" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47474", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47474", "Z47474K1": { "Z1K1": "Z6091", "Z6091K1": "Q8041" }, "Z47474K2": { "Z1K1": "Z60", "Z60K1": "es" }, "Z47474K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "Inkscape funciona en Linux, Microsoft Windows y otros." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Operating system sentence, Spanish: Inkscape" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } tlk1yg6mi4w1jhvg6i20ruqra3o0vt4 Z47973 0 101672 333883 2026-10-27T12:15:06Z Jsamwrites 938 Create Operating system sentence, Latin: Inkscape 333883 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47973" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47474", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47474", "Z47474K1": { "Z1K1": "Z6091", "Z6091K1": "Q8041" }, "Z47474K2": { "Z1K1": "Z60", "Z60K1": "la" }, "Z47474K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "Inkscape in Linux, Microsoft Windows et alia currit." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Operating system sentence, Latin: Inkscape" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } ttpvmorvedzvx95ggzefoc1278kyrim Z47974 0 101673 333884 2026-10-27T12:15:08Z Jsamwrites 938 Create Operating system sentence, Malayalam: Inkscape 333884 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47974" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47474", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47474", "Z47474K1": { "Z1K1": "Z6091", "Z6091K1": "Q8041" }, "Z47474K2": { "Z1K1": "Z60", "Z60K1": "ml" }, "Z47474K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "ഇങ്ക്‌സ്കേപ്പ് ലിനക്സിലും, മൈക്രോസോഫ്റ്റ്‌ വിൻഡോസിലും, മറ്റുള്ളവയിലും പ്രവർത്തിക്കുന്നു." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Operating system sentence, Malayalam: Inkscape" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } g23ob0de8fgru9c9w3pxb9ae349hwln Z47975 0 101674 333885 2026-10-27T12:15:09Z Jsamwrites 938 Create Operating system sentence, Igbo: Inkscape 333885 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47975" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47474", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47474", "Z47474K1": { "Z1K1": "Z6091", "Z6091K1": "Q8041" }, "Z47474K2": { "Z1K1": "Z60", "Z60K1": "ig" }, "Z47474K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "Inkscape na-arụ na Linux, Microsoft Windows na ndị ọzọ." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Operating system sentence, Igbo: Inkscape" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } mhj8fdiynlog36lluxrlvkkx6okau19 Z47976 0 101675 333886 2026-10-27T12:15:11Z Jsamwrites 938 Create Operating system sentence, Dagbani: Inkscape 333886 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47976" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47474", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47474", "Z47474K1": { "Z1K1": "Z6091", "Z6091K1": "Q8041" }, "Z47474K2": { "Z1K1": "Z60", "Z60K1": "dag" }, "Z47474K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "Inkscape tumda Linux, Microsoft Windows mini shɛba zuɣu." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Operating system sentence, Dagbani: Inkscape" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } r7j3ku6yl8llr29ccvbvgiuio1fhgrp Z47977 0 101676 333897 2026-10-27T16:14:24Z Jsamwrites 938 Create Programming language sentence (HTML), Latin: Inkscape 333897 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47977" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47653", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z89K1" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47653", "Z47653K1": { "Z1K1": "Z6091", "Z6091K1": "Q8041" }, "Z47653K2": { "Z1K1": "Z60", "Z60K1": "la" }, "Z47653K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "\u003Ca href=\"https://abstract.wikipedia.org/wiki/Q8041\"\u003EInkscape\u003C/a\u003E \u003Ca href=\"https://abstract.wikipedia.org/wiki/Q2407\"\u003EC++\u003C/a\u003E et \u003Ca href=\"https://abstract.wikipedia.org/wiki/Q15777\"\u003EC\u003C/a\u003E scribitur." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Programming language sentence (HTML), Latin: Inkscape" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 89h4l0wyqb3q1re0oxj03grwb4ezelo Z47978 0 101677 333898 2026-10-27T16:14:27Z Jsamwrites 938 Create Programming language sentence (HTML), Igbo: Inkscape 333898 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47978" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47653", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z89K1" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47653", "Z47653K1": { "Z1K1": "Z6091", "Z6091K1": "Q8041" }, "Z47653K2": { "Z1K1": "Z60", "Z60K1": "ig" }, "Z47653K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "E dere \u003Ca href=\"https://abstract.wikipedia.org/wiki/Q8041\"\u003EInkscape\u003C/a\u003E na \u003Ca href=\"https://abstract.wikipedia.org/wiki/Q2407\"\u003EC++\u003C/a\u003E na \u003Ca href=\"https://abstract.wikipedia.org/wiki/Q15777\"\u003EC\u003C/a\u003E." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Programming language sentence (HTML), Igbo: Inkscape" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 9mdz8s6ntv3tazqqj5af82j71uxxar8 Z47979 0 101678 333899 2026-10-27T16:14:28Z Jsamwrites 938 Create Programming language sentence (HTML), Dagbani: Inkscape 333899 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47979" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47653", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z89K1" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47653", "Z47653K1": { "Z1K1": "Z6091", "Z6091K1": "Q8041" }, "Z47653K2": { "Z1K1": "Z60", "Z60K1": "dag" }, "Z47653K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "Bɛ sabi \u003Ca href=\"https://abstract.wikipedia.org/wiki/Q8041\"\u003EInkscape\u003C/a\u003E \u003Ca href=\"https://abstract.wikipedia.org/wiki/Q2407\"\u003EC++\u003C/a\u003E mini \u003Ca href=\"https://abstract.wikipedia.org/wiki/Q15777\"\u003EC\u003C/a\u003E ni." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Programming language sentence (HTML), Dagbani: Inkscape" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 3uorkz47msjxzzxl3h7f96vf9osbdtu Z47980 0 101679 333900 2026-10-27T16:14:40Z Jsamwrites 938 Create Programming language sentence (HTML), Spanish: Inkscape 333900 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47980" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47653", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z89K1" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47653", "Z47653K1": { "Z1K1": "Z6091", "Z6091K1": "Q8041" }, "Z47653K2": { "Z1K1": "Z60", "Z60K1": "es" }, "Z47653K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "\u003Ca href=\"https://abstract.wikipedia.org/wiki/Q8041\"\u003EInkscape\u003C/a\u003E es escrito en \u003Ca href=\"https://abstract.wikipedia.org/wiki/Q2407\"\u003EC++\u003C/a\u003E y \u003Ca href=\"https://abstract.wikipedia.org/wiki/Q15777\"\u003EC\u003C/a\u003E." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Programming language sentence (HTML), Spanish: Inkscape" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 2p09h4y98elgrd5434rqovg3om3yz3q Z47981 0 101680 333901 2026-10-27T16:14:42Z Jsamwrites 938 Create Operating system sentence (HTML), Spanish: Inkscape 333901 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47981" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47655", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z89K1" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47655", "Z47655K1": { "Z1K1": "Z6091", "Z6091K1": "Q8041" }, "Z47655K2": { "Z1K1": "Z60", "Z60K1": "es" }, "Z47655K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "\u003Ca href=\"https://abstract.wikipedia.org/wiki/Q8041\"\u003EInkscape\u003C/a\u003E funciona en \u003Ca href=\"https://abstract.wikipedia.org/wiki/Q388\"\u003ELinux\u003C/a\u003E, \u003Ca href=\"https://abstract.wikipedia.org/wiki/Q1406\"\u003EMicrosoft Windows\u003C/a\u003E y otros." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Operating system sentence (HTML), Spanish: Inkscape" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } k9jx7td9lqfqsvuo7vdg4khxv3ejcry Z47982 0 101681 333904 2026-10-27T16:25:12Z ReXLer 39813 333904 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47982" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47127", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z47127", "Z47127K1": { "Z1K1": "Z7", "Z7K1": "Z6821", "Z6821K1": { "Z1K1": "Z6091", "Z6091K1": "Q928" } }, "Z47127K2": "Z1002" }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z844", "Z844K2": { "Z1K1": "Z40", "Z40K1": "Z41" } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Philippines, English: true" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 0nggokeusk5qc2epsnxrr1pr4nlpl9z 333907 333904 2026-10-27T16:27:37Z ReXLer 39813 333907 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47982" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47127", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z47127", "Z47127K1": { "Z1K1": "Z7", "Z7K1": "Z6821", "Z6821K1": { "Z1K1": "Z6091", "Z6091K1": "Q928" } }, "Z47127K2": "Z1002" }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z844", "Z844K2": { "Z1K1": "Z40", "Z40K1": "Z42" } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Philippines, English: false" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } o6bf9138nv18ixgiqwhj5rs282vwb2u Z47983 0 101682 333909 2026-10-27T19:02:06Z Jsamwrites 938 Create Operating system sentence (HTML), Igbo: Inkscape 333909 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47983" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47655", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z89K1" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47655", "Z47655K1": { "Z1K1": "Z6091", "Z6091K1": "Q8041" }, "Z47655K2": { "Z1K1": "Z60", "Z60K1": "ig" }, "Z47655K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "\u003Ca href=\"https://abstract.wikipedia.org/wiki/Q8041\"\u003EInkscape\u003C/a\u003E na-arụ na \u003Ca href=\"https://abstract.wikipedia.org/wiki/Q388\"\u003ELinux\u003C/a\u003E, \u003Ca href=\"https://abstract.wikipedia.org/wiki/Q1406\"\u003EMicrosoft Windows\u003C/a\u003E na ndị ọzọ." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Operating system sentence (HTML), Igbo: Inkscape" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } djgoe2itqc4yw3yd7x6jved787kfonc Z47984 0 101683 333910 2026-10-27T19:03:03Z Jsamwrites 938 Create Founder sentence (HTML), Latin: Google 333910 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47984" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47647", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z89K1" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47647", "Z47647K1": { "Z1K1": "Z6091", "Z6091K1": "Q95" }, "Z47647K2": { "Z1K1": "Z60", "Z60K1": "la" }, "Z47647K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "\u003Ca href=\"https://abstract.wikipedia.org/wiki/Q92764\"\u003ESergius Brin\u003C/a\u003E et \u003Ca href=\"https://abstract.wikipedia.org/wiki/Q4934\"\u003ELaurentius Page\u003C/a\u003E \u003Ca href=\"https://abstract.wikipedia.org/wiki/Q95\"\u003EGoogle\u003C/a\u003E condiderunt." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Founder sentence (HTML), Latin: Google" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } rpsn0yiraesymxss88z5u335mccmuo9 Translations:Wikifunctions:Status updates/2026-10-25/3/de 1198 101684 333911 2026-10-27T19:03:27Z Ameisenigel 44 Created page with "=== Wikiabstrak-App ===" 333911 wikitext text/x-wiki === Wikiabstrak-App === li3v4xxldiwcdjyx1wft93czs2y69w4 Translations:Wikifunctions:Status updates/2026-10-25/4/de 1198 101685 333915 2026-10-27T19:04:14Z Ameisenigel 44 Created page with "Eine neue App wurde von [[$1|Affandy Murad]], einem Freiwilligen in der indonesischen Wikipedia und anderen Projekten, entwickelt: [$2 Wikiabstrak]." 333915 wikitext text/x-wiki Eine neue App wurde von [[$1|Affandy Murad]], einem Freiwilligen in der indonesischen Wikipedia und anderen Projekten, entwickelt: [$2 Wikiabstrak]. oyks7vrw2feafkhudu7k1jm2ckaw1m8 Translations:Wikifunctions:Status updates/2026-10-25/5/de 1198 101686 333917 2026-10-27T19:04:37Z Ameisenigel 44 Created page with "Die App selbst beschreibt sich wie folgt:" 333917 wikitext text/x-wiki Die App selbst beschreibt sich wie folgt: p2o4yipt6wgzz0msdjo2t5r08hd9il5 Translations:Wikifunctions:Status updates/2026-10-25/6/de 1198 101687 333919 2026-10-27T19:06:10Z Ameisenigel 44 Created page with "''“Wikiabstrak ist ein offenes Experiment, das strukturierte Daten aus Wikidata in lesbare Zusammenfassungen umwandelt, ganz ohne Sprachmodell (LLM). Sucht man nach einem Land, einem Ort, einer Person oder einem Gebäude, erstellt das System anhand fester Regeln einen Textabschnitt aus Wikidata-Aussagen, sodass sich jeder Satz auf seine Quelle zurückführen lässt.''" 333919 wikitext text/x-wiki ''“Wikiabstrak ist ein offenes Experiment, das strukturierte Daten aus Wikidata in lesbare Zusammenfassungen umwandelt, ganz ohne Sprachmodell (LLM). Sucht man nach einem Land, einem Ort, einer Person oder einem Gebäude, erstellt das System anhand fester Regeln einen Textabschnitt aus Wikidata-Aussagen, sodass sich jeder Satz auf seine Quelle zurückführen lässt.'' jf5xhz9yhffqqk9wrkz5y9lwrb1l4z5 Translations:Wikifunctions:Status updates/2026-10-25/7/de 1198 101688 333921 2026-10-27T19:08:33Z Ameisenigel 44 Created page with "''“Zudem werden wichtige Fakten, Fotos von Wikimedia Commons sowie Links zu sämtlichen Wikimedia-Projekten angezeigt und es gibt eine vorgefertigte Vorlage für den Einleitungsabsatz für die Abstrakte Wikipedia, die es dir ermöglicht, sprachunabhängige Artikel zu erstellen oder zu bearbeiten.”''" 333921 wikitext text/x-wiki ''“Zudem werden wichtige Fakten, Fotos von Wikimedia Commons sowie Links zu sämtlichen Wikimedia-Projekten angezeigt und es gibt eine vorgefertigte Vorlage für den Einleitungsabsatz für die Abstrakte Wikipedia, die es dir ermöglicht, sprachunabhängige Artikel zu erstellen oder zu bearbeiten.”'' 1fq71un4kur6rjatph0ssej4kzhs6a3 Translations:Wikifunctions:Status updates/2026-10-25/8/de 1198 101689 333923 2026-10-27T19:12:32Z Ameisenigel 44 Created page with "Viel Spaß bei der Nutzung der App! Falls du Vorschläge hast, kannst du Affandy im Telegram-/IRC-Chat des Projekts oder auf [[$1|seiner Benutzerdiskussionsseite]] kontaktieren. Schau dir auch die weiteren Apps an, die Affandy entwickelt hat und die auf [[$2|seiner Benutzerseite]] aufgelistet sind." 333923 wikitext text/x-wiki Viel Spaß bei der Nutzung der App! Falls du Vorschläge hast, kannst du Affandy im Telegram-/IRC-Chat des Projekts oder auf [[$1|seiner Benutzerdiskussionsseite]] kontaktieren. Schau dir auch die weiteren Apps an, die Affandy entwickelt hat und die auf [[$2|seiner Benutzerseite]] aufgelistet sind. e07bnx2xqmkhcp5c014vv6ezvxlaci2 Translations:Wikifunctions:Status updates/2026-10-25/9/de 1198 101690 333925 2026-10-27T19:12:59Z Ameisenigel 44 Created page with "=== Keine Änderungen an der Software in dieser Woche ===" 333925 wikitext text/x-wiki === Keine Änderungen an der Software in dieser Woche === pzgui4h1l3b1r4vwtu834tcvf2nydez Z47985 0 101691 333927 2026-10-27T19:18:16Z Jsamwrites 938 Create Publication date sentence: Latin 333927 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47985" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47099", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47099", "Z47099K1": { "Z1K1": "Z6091", "Z6091K1": "Q180736" }, "Z47099K2": { "Z1K1": "Z60", "Z60K1": "la" }, "Z47099K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "Anno MDCCCLXII Les Misérables ediderunt." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Publication date sentence: Latin" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } d5k474r6090rho07ihf5lycpqq4visr Z47986 0 101692 333928 2026-10-27T19:18:18Z Jsamwrites 938 Create Publication date sentence: Malayalam 333928 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47986" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47099", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47099", "Z47099K1": { "Z1K1": "Z6091", "Z6091K1": "Q180736" }, "Z47099K2": { "Z1K1": "Z60", "Z60K1": "ml" }, "Z47099K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "ലെ മിസേറാബ്ലെ 1862-ൽ പ്രസിദ്ധീകരിക്കപ്പെട്ടു." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Publication date sentence: Malayalam" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } so6l8p4bje23h7mpfurwd5pkrxg29l1 Z47987 0 101693 333929 2026-10-27T19:18:20Z Jsamwrites 938 Create Publication date sentence: Dagbani 333929 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47987" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47099", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47099", "Z47099K1": { "Z1K1": "Z6091", "Z6091K1": "Q180736" }, "Z47099K2": { "Z1K1": "Z60", "Z60K1": "dag" }, "Z47099K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "Bɛ daa moli Les Misérables yuuni 1862 ni." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Publication date sentence: Dagbani" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } oa6rsqskht1a8a9zno9i3ts62mb4wxq Z47988 0 101694 333931 2026-10-27T19:19:10Z Jsamwrites 938 Create Publication date sentence: Spanish 333931 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47988" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47099", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47099", "Z47099K1": { "Z1K1": "Z6091", "Z6091K1": "Q180736" }, "Z47099K2": { "Z1K1": "Z60", "Z60K1": "es" }, "Z47099K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "Los miserables fue publicado en 1862." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Publication date sentence: Spanish" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } nh4rqfgmj8e9pnq6kgon469mbw281ey Z47989 0 101695 333932 2026-10-27T19:19:12Z Jsamwrites 938 Create Publication date sentence: Igbo 333932 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47989" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47099", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47099", "Z47099K1": { "Z1K1": "Z6091", "Z6091K1": "Q180736" }, "Z47099K2": { "Z1K1": "Z60", "Z60K1": "ig" }, "Z47099K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "E bipụtara Les Misérables na 1862." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Publication date sentence: Igbo" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 9auetbeyrecusqb8dzcozm0cmaz7age Z47990 0 101696 333933 2026-10-27T19:19:14Z Jsamwrites 938 Create Operating system sentence (HTML), Malayalam: Inkscape 333933 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47990" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47655", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z89K1" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47655", "Z47655K1": { "Z1K1": "Z6091", "Z6091K1": "Q8041" }, "Z47655K2": { "Z1K1": "Z60", "Z60K1": "ml" }, "Z47655K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "\u003Ca href=\"https://abstract.wikipedia.org/wiki/Q8041\"\u003Eഇങ്ക്‌സ്കേപ്പ്\u003C/a\u003E \u003Ca href=\"https://abstract.wikipedia.org/wiki/Q388\"\u003Eലിനക്സിലും\u003C/a\u003E, \u003Ca href=\"https://abstract.wikipedia.org/wiki/Q1406\"\u003Eമൈക്രോസോഫ്റ്റ്‌ വിൻഡോസിലും\u003C/a\u003E, മറ്റുള്ളവയിലും പ്രവർത്തിക്കുന്നു." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Operating system sentence (HTML), Malayalam: Inkscape" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } rdeoc5c6poyq9wb9crrt27712urgaah Translations:Wikifunctions:How to create implementations/331/de 1198 101697 333935 2026-10-27T19:21:31Z Ameisenigel 44 Created page with "=== Erstellung handlungsorientierter Fehlermeldungen ===" 333935 wikitext text/x-wiki === Erstellung handlungsorientierter Fehlermeldungen === hspgyefp8ud2h02lcp3puskamidfigm Translations:Wikifunctions:How to create implementations/332/de 1198 101698 333937 2026-10-27T19:25:03Z Ameisenigel 44 Created page with "Wie oben beschrieben, verfügen Fehlertypen über einen optionalen Schlüssel $1, der eine mehrsprachige Liste von HTML-Zeichenketten enthält. Bei der Darstellung von Informationen zu einem Fehler können die im Fehlertyp hinterlegten Meldungen dazu beitragen, eine klare, präzise, ​​informative, übersetzbare und handlungsorientierte Fehlermeldung zu erstellen." 333937 wikitext text/x-wiki Wie oben beschrieben, verfügen Fehlertypen über einen optionalen Schlüssel $1, der eine mehrsprachige Liste von HTML-Zeichenketten enthält. Bei der Darstellung von Informationen zu einem Fehler können die im Fehlertyp hinterlegten Meldungen dazu beitragen, eine klare, präzise, ​​informative, übersetzbare und handlungsorientierte Fehlermeldung zu erstellen. mannxifcfk1kkugxc0k65e5qnswx9og Translations:Wikifunctions:How to create implementations/333/de 1198 101699 333939 2026-10-27T19:27:48Z Ameisenigel 44 Created page with "Zu diesem Zweck können Fehlermeldungen Parameter wie $1, $2 etc. enthalten, wobei die Ziffer dem Argument des Fehlertyps und dessen Wert in der Fehlerinstanz entspricht. Diese Fehlermeldungen werden in Wikifunctions nach der Ausführung eines Funktionsaufrufs im Dialogfenster "Details" angezeigt. Darüber hinaus werden diese Fehlermeldungen auch in anderen Client-Schnittstellen, wie der Abstrakten Wikipedia, ausgegeben, um den Autoren von Abstrakten Inhalten eine besser..." 333939 wikitext text/x-wiki Zu diesem Zweck können Fehlermeldungen Parameter wie $1, $2 etc. enthalten, wobei die Ziffer dem Argument des Fehlertyps und dessen Wert in der Fehlerinstanz entspricht. Diese Fehlermeldungen werden in Wikifunctions nach der Ausführung eines Funktionsaufrufs im Dialogfenster "Details" angezeigt. Darüber hinaus werden diese Fehlermeldungen auch in anderen Client-Schnittstellen, wie der Abstrakten Wikipedia, ausgegeben, um den Autoren von Abstrakten Inhalten eine bessere Orientierung zu bieten. bxo3fos8vhrk8urazab6nvtwmjsqrv1 Translations:Wikifunctions:How to create implementations/334/de 1198 101700 333941 2026-10-27T19:27:58Z Ameisenigel 44 Created page with "Die Fehlermeldung wird unter Verwendung der HTML-Meldung des Fehlertyps und der Werte der Fehlerargumente generiert." 333941 wikitext text/x-wiki Die Fehlermeldung wird unter Verwendung der HTML-Meldung des Fehlertyps und der Werte der Fehlerargumente generiert. 6w6cheykrwdgxgw4ev01j4r8kdgaiyq Translations:Wikifunctions:How to create implementations/335/de 1198 101701 333943 2026-10-27T19:28:05Z Ameisenigel 44 Created page with "Sofern verfügbar, wird die HTML-Fehlermeldung im Vorschau-Bereich der Abstrakten Wikipedia angezeigt." 333943 wikitext text/x-wiki Sofern verfügbar, wird die HTML-Fehlermeldung im Vorschau-Bereich der Abstrakten Wikipedia angezeigt. 6n7pe9crexafqqlomdyp5bbzfheq1gn Translations:Wikifunctions:How to create implementations/336/de 1198 101702 333945 2026-10-27T19:29:16Z Ameisenigel 44 Created page with "Lass uns anhand eines konkreten Beispiels die Vorteile von HTML-Fehlermeldungen nachvollziehen:" 333945 wikitext text/x-wiki Lass uns anhand eines konkreten Beispiels die Vorteile von HTML-Fehlermeldungen nachvollziehen: 8o7pfrnk9soli0vwpm2l4wdvgiirdqt Z47991 0 101703 333957 2026-10-27T20:08:04Z Jsamwrites 938 Create Depends on sentence (HTML), English pronoun: LaTeX 333957 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47991" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47685", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z89K1" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47685", "Z47685K1": { "Z1K1": "Z6091", "Z6091K1": "Q5310" }, "Z47685K2": { "Z1K1": "Z60", "Z60K1": "en" }, "Z47685K3": [ "Z39328", { "Z1K1": "Z39328", "Z39328K1": { "Z1K1": "Z6091", "Z6091K1": "Q3427356" }, "Z39328K2": { "Z1K1": "Z6091", "Z6091K1": "Q468801" } } ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "It depends on \u003Ca href=\"https://abstract.wikipedia.org/wiki/Q5301\"\u003ETeX\u003C/a\u003E." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Depends on sentence (HTML), English pronoun: LaTeX" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } ongpon3v88enb5k3uj47qmiu3c63gyj Z47992 0 101704 333958 2026-10-27T20:08:06Z Jsamwrites 938 Create Platform sentence (HTML), English pronoun: Facebook 333958 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47992" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47687", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z89K1" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47687", "Z47687K1": { "Z1K1": "Z6091", "Z6091K1": "Q355" }, "Z47687K2": { "Z1K1": "Z60", "Z60K1": "en" }, "Z47687K3": [ "Z39328", { "Z1K1": "Z39328", "Z39328K1": { "Z1K1": "Z6091", "Z6091K1": "Q3427356" }, "Z39328K2": { "Z1K1": "Z6091", "Z6091K1": "Q468801" } } ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "It runs on \u003Ca href=\"https://abstract.wikipedia.org/wiki/Q48493\"\u003EiOS\u003C/a\u003E \u003Ca href=\"https://abstract.wikipedia.org/wiki/Q94\"\u003Eand\u003C/a\u003E \u003Ca href=\"https://abstract.wikipedia.org/wiki/Q94\"\u003EAndroid\u003C/a\u003E." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Platform sentence (HTML), English pronoun: Facebook" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } cu3bmxmbbhqz06i0s03em03k2x4ss1b Z47993 0 101705 333959 2026-10-27T20:08:08Z Jsamwrites 938 Create Software engine sentence (HTML), English pronoun: Wikipedia 333959 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47993" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47705", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z89K1" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47705", "Z47705K1": { "Z1K1": "Z6091", "Z6091K1": "Q52" }, "Z47705K2": { "Z1K1": "Z60", "Z60K1": "en" }, "Z47705K3": [ "Z39328", { "Z1K1": "Z39328", "Z39328K1": { "Z1K1": "Z6091", "Z6091K1": "Q3427356" }, "Z39328K2": { "Z1K1": "Z6091", "Z6091K1": "Q468801" } } ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "It uses \u003Ca href=\"https://abstract.wikipedia.org/wiki/Q83\"\u003EMediaWiki\u003C/a\u003E." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Software engine sentence (HTML), English pronoun: Wikipedia" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } n82d18vldq3ibnz1uouq0gmefekldr0 Z47994 0 101706 333960 2026-10-27T20:08:10Z Jsamwrites 938 Create Licence sentence (HTML), English pronoun: HTML 333960 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47994" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47715", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z89K1" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47715", "Z47715K1": { "Z1K1": "Z6091", "Z6091K1": "Q8811" }, "Z47715K2": { "Z1K1": "Z60", "Z60K1": "en" }, "Z47715K3": [ "Z39328", { "Z1K1": "Z39328", "Z39328K1": { "Z1K1": "Z6091", "Z6091K1": "Q3427356" }, "Z39328K2": { "Z1K1": "Z6091", "Z6091K1": "Q468801" } } ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "It is released under \u003Ca href=\"https://abstract.wikipedia.org/wiki/Q20007257\"\u003ECreative Commons Attribution 4.0 International\u003C/a\u003E." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Licence sentence (HTML), English pronoun: HTML" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } gq57tlxusr5oofcvzhmlbtvjknezksx Z47995 0 101707 333966 2026-10-27T22:15:43Z ReXLer 39813 333966 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47995" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z47995K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "escaped HTML fragment" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14" ], "Z8K5": "Z47995" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape named HTML characters (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } qvzlrm7flw8fyx1fhqqx098f36hamf3 333968 333966 2026-10-27T22:16:19Z ReXLer 39813 Added Z47996 to the approved list of implementations 333968 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47995" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z47995K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "escaped HTML fragment" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14", "Z47996" ], "Z8K5": "Z47995" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape named HTML characters (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 9ue61bwtns3le5vyxdgj0gb4h07x025 333969 333968 2026-10-27T22:16:32Z ReXLer 39813 Removed Z47996 from the approved list of implementations 333969 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47995" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z47995K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "escaped HTML fragment" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14" ], "Z8K5": "Z47995" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape named HTML characters (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } qvzlrm7flw8fyx1fhqqx098f36hamf3 333971 333969 2026-10-27T22:17:09Z ReXLer 39813 Added Z47996 to the approved list of implementations 333971 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47995" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z47995K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "escaped HTML fragment" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14", "Z47996" ], "Z8K5": "Z47995" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape named HTML characters (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 9ue61bwtns3le5vyxdgj0gb4h07x025 333972 333971 2026-10-27T22:17:16Z ReXLer 39813 Removed Z47996 from the approved list of implementations 333972 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47995" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z47995K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "escaped HTML fragment" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14" ], "Z8K5": "Z47995" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape named HTML characters (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } qvzlrm7flw8fyx1fhqqx098f36hamf3 333974 333972 2026-10-27T22:17:59Z ReXLer 39813 Added Z47996 to the approved list of implementations 333974 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47995" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z47995K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "escaped HTML fragment" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14", "Z47996" ], "Z8K5": "Z47995" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape named HTML characters (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 9ue61bwtns3le5vyxdgj0gb4h07x025 333975 333974 2026-10-27T22:18:07Z ReXLer 39813 Removed Z47996 from the approved list of implementations 333975 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47995" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z47995K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "escaped HTML fragment" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14" ], "Z8K5": "Z47995" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape named HTML characters (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } qvzlrm7flw8fyx1fhqqx098f36hamf3 333977 333975 2026-10-27T22:18:50Z ReXLer 39813 Added Z47996 to the approved list of implementations 333977 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47995" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z47995K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "escaped HTML fragment" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14", "Z47996" ], "Z8K5": "Z47995" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape named HTML characters (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 9ue61bwtns3le5vyxdgj0gb4h07x025 333978 333977 2026-10-27T22:19:35Z ReXLer 39813 Removed Z47996 from the approved list of implementations 333978 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47995" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z47995K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "escaped HTML fragment" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14" ], "Z8K5": "Z47995" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape named HTML characters (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } qvzlrm7flw8fyx1fhqqx098f36hamf3 333988 333978 2026-10-27T22:30:45Z ReXLer 39813 Added Z47996 to the approved list of implementations 333988 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47995" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z47995K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "escaped HTML fragment" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14", "Z47996" ], "Z8K5": "Z47995" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape named HTML characters (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 9ue61bwtns3le5vyxdgj0gb4h07x025 333990 333988 2026-10-27T22:33:31Z ReXLer 39813 Removed Z47996 from the approved list of implementations 333990 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47995" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z47995K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "escaped HTML fragment" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14" ], "Z8K5": "Z47995" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape named HTML characters (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } qvzlrm7flw8fyx1fhqqx098f36hamf3 333992 333990 2026-10-27T22:35:46Z ReXLer 39813 Added Z47996 to the approved list of implementations 333992 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47995" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z47995K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "escaped HTML fragment" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14", "Z47996" ], "Z8K5": "Z47995" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape named HTML characters (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 9ue61bwtns3le5vyxdgj0gb4h07x025 333993 333992 2026-10-27T22:36:12Z ReXLer 39813 Removed Z47996 from the approved list of implementations 333993 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47995" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z47995K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "escaped HTML fragment" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14" ], "Z8K5": "Z47995" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape named HTML characters (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } qvzlrm7flw8fyx1fhqqx098f36hamf3 333994 333993 2026-10-27T22:36:14Z ReXLer 39813 Added Z47996 to the approved list of implementations 333994 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47995" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z47995K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "escaped HTML fragment" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14", "Z47996" ], "Z8K5": "Z47995" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape named HTML characters (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 9ue61bwtns3le5vyxdgj0gb4h07x025 333995 333994 2026-10-27T22:36:20Z ReXLer 39813 Removed Z47996 from the approved list of implementations 333995 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47995" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z47995K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "escaped HTML fragment" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14" ], "Z8K5": "Z47995" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape named HTML characters (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } qvzlrm7flw8fyx1fhqqx098f36hamf3 333996 333995 2026-10-27T22:36:51Z ReXLer 39813 Added Z47996 to the approved list of implementations 333996 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47995" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z47995K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "escaped HTML fragment" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14", "Z47996" ], "Z8K5": "Z47995" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape named HTML characters (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 9ue61bwtns3le5vyxdgj0gb4h07x025 333997 333996 2026-10-27T22:36:59Z ReXLer 39813 Removed Z47996 from the approved list of implementations 333997 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47995" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z47995K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "escaped HTML fragment" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14" ], "Z8K5": "Z47995" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape named HTML characters (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } qvzlrm7flw8fyx1fhqqx098f36hamf3 333999 333997 2026-10-27T22:37:42Z ReXLer 39813 Added Z47996 to the approved list of implementations 333999 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47995" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z47995K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "escaped HTML fragment" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14", "Z47996" ], "Z8K5": "Z47995" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape named HTML characters (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 9ue61bwtns3le5vyxdgj0gb4h07x025 334000 333999 2026-10-27T22:37:50Z ReXLer 39813 Removed Z47996 from the approved list of implementations 334000 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47995" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z47995K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "escaped HTML fragment" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14" ], "Z8K5": "Z47995" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape named HTML characters (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } qvzlrm7flw8fyx1fhqqx098f36hamf3 334002 334000 2026-10-27T22:39:22Z ReXLer 39813 Added Z47996 to the approved list of implementations 334002 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47995" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z47995K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "escaped HTML fragment" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14", "Z47996" ], "Z8K5": "Z47995" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape named HTML characters (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 9ue61bwtns3le5vyxdgj0gb4h07x025 334004 334002 2026-10-27T22:39:57Z ReXLer 39813 Added Z48000 to the approved list of test cases 334004 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47995" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z47995K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "escaped HTML fragment" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20", "Z48000" ], "Z8K4": [ "Z14", "Z47996" ], "Z8K5": "Z47995" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape named HTML characters (HTML)" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } f5d1gt97jkk5fbofylf3jkdq39bhosq Z47996 0 101708 333967 2026-10-27T22:16:10Z ReXLer 39813 333967 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47996" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z47995", "Z14K3": { "Z1K1": "Z16", "Z16K1": "Z610", "Z16K2": "def Z47995(Z47995K1):\n\timport html\n\treturn html.unescape(Z47995K1)" } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape HTML, py" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } mwn46k123dir1hcndql7qmbqj9tfzro 333970 333967 2026-10-27T22:16:52Z ReXLer 39813 333970 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47996" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z47995", "Z14K3": { "Z1K1": "Z16", "Z16K1": "Z610", "Z16K2": "def Z47995(Z47995K1):\n\timport html\n\treturn html.unescape(str(Z47995K1))" } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape HTML, py" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } qegi8yk3b47burwb8ug843d8449z8ef 333973 333970 2026-10-27T22:17:46Z ReXLer 39813 333973 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47996" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z47995", "Z14K3": { "Z1K1": "Z16", "Z16K1": "Z610", "Z16K2": "def Z47995(Z47995K1):\n\timport html\n\treturn ZObject(html.unescape(str(Z47995K1)))" } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape HTML, py" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } en5l61w4qjjeur2trttxlbjrdq0cyyz 333976 333973 2026-10-27T22:18:47Z ReXLer 39813 333976 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47996" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z47995", "Z14K3": { "Z1K1": "Z16", "Z16K1": "Z610", "Z16K2": "def Z47995(Z47995K1):\n\timport html\n\treturn html.unescape(str(Z47995K1))" } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape HTML, py" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } qegi8yk3b47burwb8ug843d8449z8ef 333987 333976 2026-10-27T22:30:32Z ReXLer 39813 333987 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47996" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z47995", "Z14K3": { "Z1K1": "Z16", "Z16K1": "Z610", "Z16K2": "def Z47995(Z47995K1):\n\timport html\n\treturn html.unescape(Z47995K1.Z89K1)" } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape HTML, py" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } qh6zk23p48fy31785vwuvjrxkpzu9m1 333989 333987 2026-10-27T22:32:32Z ReXLer 39813 hmmmm 333989 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47996" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z47995", "Z14K3": { "Z1K1": "Z16", "Z16K1": "Z610", "Z16K2": "def Z47995(Z47995K1):\n\timport html\n\treturn {Z1K1:{Z1K1:\"Z9\",Z9K1:\"Z89\"}, Z89K1:html.unescape(Z47995K1.Z89K1)}" } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape HTML, py" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } fs7pcauvvwh6fxy7l6lv2elf5o3xsst 333991 333989 2026-10-27T22:35:35Z ReXLer 39813 ok this shall work 333991 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47996" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z47995", "Z14K3": { "Z1K1": "Z16", "Z16K1": "Z600", "Z16K2": "function Z47995( Z47995K1 ) {\n\tlet s=Z47995K1.replaceAll('\u0026amp;',\"\u0026\");\n\ts=s.replaceAll(\"\u0026quot;\", '\"');\n\ts=s.replaceAll(\"\u0026apos;\", \"'\");\n\ts=s.replaceAll(\"\u0026lt;\", '\u003C');\n\ts=s.replaceAll(\"\u0026gt;\", '\u003E');\n\treturn {Z1K1:{Z1K1:\"Z9\",Z9K1:\"Z89\"}, Z89K1:s};\n}" } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape HTML, js" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } k4lyaihph67koqqciqjjjath7202fa3 333998 333991 2026-10-27T22:37:33Z ReXLer 39813 333998 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47996" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z47995", "Z14K3": { "Z1K1": "Z16", "Z16K1": "Z600", "Z16K2": "function Z47996( Z47996K1 ) {\n\tlet s=Z47996K1.replaceAll('\u0026amp;',\"\u0026\");\n\ts=s.replaceAll(\"\u0026quot;\", '\"');\n\ts=s.replaceAll(\"\u0026apos;\", \"'\");\n\ts=s.replaceAll(\"\u0026lt;\", '\u003C');\n\ts=s.replaceAll(\"\u0026gt;\", '\u003E');\n\treturn {Z1K1:{Z1K1:\"Z9\",Z9K1:\"Z89\"}, Z89K1:s};\n}" } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape HTML, js" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } ayf4kfec8b0ykarf4s39ehykz5pzedh 334001 333998 2026-10-27T22:39:17Z ReXLer 39813 334001 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47996" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z47995", "Z14K3": { "Z1K1": "Z16", "Z16K1": "Z600", "Z16K2": "function Z47995( Z47995K1 ) {\n\tlet r=Z47995K1.Z89K1\n\tlet s=r.replaceAll('\u0026amp;',\"\u0026\");\n\ts=s.replaceAll(\"\u0026quot;\", '\"');\n\ts=s.replaceAll(\"\u0026apos;\", \"'\");\n\ts=s.replaceAll(\"\u0026lt;\", '\u003C');\n\ts=s.replaceAll(\"\u0026gt;\", '\u003E');\n\treturn {Z1K1:{Z1K1:\"Z9\",Z9K1:\"Z89\"}, Z89K1:s};\n}" } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape HTML, js" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 31x27fae1px9wjbgq1ipwp9suna419g Z47997 0 101709 333979 2026-10-27T22:24:03Z ReXLer 39813 333979 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47997" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6", "Z17K2": "Z47997K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "string" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14" ], "Z8K5": "Z47997" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "string to HTML, no escaping" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } gohiw7rdc06sykh5kr7inm73r71rafz 333981 333979 2026-10-27T22:25:22Z ReXLer 39813 Added Z47998 to the approved list of implementations 333981 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47997" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6", "Z17K2": "Z47997K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "string" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14", "Z47998" ], "Z8K5": "Z47997" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "string to HTML, no escaping" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } idm8bzdvnf1way3aqx6e7i8638cq2be 333982 333981 2026-10-27T22:25:28Z ReXLer 39813 Removed Z47998 from the approved list of implementations 333982 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47997" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6", "Z17K2": "Z47997K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "string" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14" ], "Z8K5": "Z47997" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "string to HTML, no escaping" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } gohiw7rdc06sykh5kr7inm73r71rafz 333983 333982 2026-10-27T22:25:36Z ReXLer 39813 Added Z47998 to the approved list of implementations 333983 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47997" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6", "Z17K2": "Z47997K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "string" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14", "Z47998" ], "Z8K5": "Z47997" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "string to HTML, no escaping" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } idm8bzdvnf1way3aqx6e7i8638cq2be 333984 333983 2026-10-27T22:26:03Z ReXLer 39813 333984 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47997" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6", "Z17K2": "Z47997K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "string" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14", "Z47998" ], "Z8K5": "Z47997" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "string to HTML, no escaping" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Useful for when you are converting a string with html tags to html" } ] } } a2ms9t36tyg7ahivoi4ty6j6rm5rz4b 333986 333984 2026-10-27T22:26:42Z ReXLer 39813 Added Z47999 to the approved list of test cases 333986 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47997" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6", "Z17K2": "Z47997K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "string" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20", "Z47999" ], "Z8K4": [ "Z14", "Z47998" ], "Z8K5": "Z47997" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "string to HTML, no escaping" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Useful for when you are converting a string with html tags to html" } ] } } raue1pfzraiw0qxjcl9jkges7c0073q Z47998 0 101710 333980 2026-10-27T22:25:09Z ReXLer 39813 333980 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47998" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z47997", "Z14K3": { "Z1K1": "Z16", "Z16K1": "Z600", "Z16K2": "function Z47997( Z47997K1 ) {\n\treturn {Z1K1:{Z1K1:\"Z9\",Z9K1:\"Z89\"}, Z89K1:Z47997K1};\n}" } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Js string to html" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } l4onvql2bo1maug91tessfaouj5an4j Z47999 0 101711 333985 2026-10-27T22:26:33Z ReXLer 39813 333985 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z47999" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47997", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z47997", "Z47997K1": "\u003Ci\u003EHi!\u003C/i\u003E" }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z877", "Z877K2": { "Z1K1": "Z89", "Z89K1": "\u003Ci\u003EHi!\u003C/i\u003E" } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "italic Hi!" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 90je2zaepu2d2jdkzq0kt8tfdw54e9c Z48000 0 101712 334003 2026-10-27T22:39:42Z ReXLer 39813 334003 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48000" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47995", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z47995", "Z47995K1": { "Z1K1": "Z89", "Z89K1": "\u0026lt;i\u0026gt;Hi!\u0026lt;/i\u0026gt;" } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z877", "Z877K2": { "Z1K1": "Z89", "Z89K1": "\u003Ci\u003EHi!\u003C/i\u003E" } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "unescape italic Hi!" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 2whg0765engutsndgvct08ze0ql2okv Z48001 0 101713 334005 2026-10-27T22:40:49Z Virinas-code 2884 334005 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48001" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6006", "Z17K2": "Z48001K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "sense" }, { "Z1K1": "Z11", "Z11K1": "Z1004", "Z11K2": "signification" } ] } } ], "Z8K2": { "Z1K1": "Z7", "Z7K1": "Z883", "Z883K1": "Z60", "Z883K2": { "Z1K1": "Z7", "Z7K1": "Z881", "Z881K1": "Z6003" } }, "Z8K3": [ "Z20" ], "Z8K4": [ "Z14" ], "Z8K5": "Z48001" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Translations of lexeme per language" }, { "Z1K1": "Z11", "Z11K1": "Z1004", "Z11K2": "Traductions d'un léxème par langue" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31", { "Z1K1": "Z31", "Z31K1": "Z1002", "Z31K2": [ "Z6", "group translations of lexeme sense by language" ] } ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "returns translation claims of a lexeme grouped by the translation's language" }, { "Z1K1": "Z11", "Z11K1": "Z1004", "Z11K2": "renvoie les traductions d'un léxème groupées par la langue de la traduction" } ] } } hnzpxn2x5hkysb06resotx9y27tadfr 334007 334005 2026-10-27T22:51:17Z Virinas-code 2884 Added Z48002 to the approved list of implementations 334007 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48001" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6006", "Z17K2": "Z48001K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "sense" }, { "Z1K1": "Z11", "Z11K1": "Z1004", "Z11K2": "signification" } ] } } ], "Z8K2": { "Z1K1": "Z7", "Z7K1": "Z883", "Z883K1": "Z60", "Z883K2": { "Z1K1": "Z7", "Z7K1": "Z881", "Z881K1": "Z6003" } }, "Z8K3": [ "Z20" ], "Z8K4": [ "Z14", "Z48002" ], "Z8K5": "Z48001" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Translations of lexeme per language" }, { "Z1K1": "Z11", "Z11K1": "Z1004", "Z11K2": "Traductions d'un léxème par langue" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31", { "Z1K1": "Z31", "Z31K1": "Z1002", "Z31K2": [ "Z6", "group translations of lexeme sense by language" ] } ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "returns translation claims of a lexeme grouped by the translation's language" }, { "Z1K1": "Z11", "Z11K1": "Z1004", "Z11K2": "renvoie les traductions d'un léxème groupées par la langue de la traduction" } ] } } ckrxd20atjuwm843lsgtho00561au6o Z48002 0 101714 334006 2026-10-27T22:51:05Z Virinas-code 2884 334006 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48002" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z48001", "Z14K3": { "Z1K1": "Z16", "Z16K1": "Z600", "Z16K2": "function Z48001( Z48001K1 ) {\n\tlet z1 = new Array();\n\tfor (let z2 of Z48001K1.Z6006K3) {\n\t\tif (z2.Z6003K2.Z6092K1 === \"P5972\") {\n\t\t\tz1.push(z2);\n\t\t}\n\t}\n\treturn z1;\n}" } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Translations of lexeme per language, JS" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 6ekpr7e1va5du2623w8m1rsizsrgpnz Z48003 0 101715 334008 2026-10-27T22:53:06Z ReXLer 39813 334008 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48003" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z48003K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6", "Z17K2": "Z48003K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "replacement label" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14" ], "Z8K5": "Z48003" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "replace specific item's label in HTML fragment" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } kai9m8fl4arli2gtot3snzehcuxic96 334009 334008 2026-10-27T22:53:29Z ReXLer 39813 334009 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48003" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z48003K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6", "Z17K2": "Z48003K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "replacement label" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z48003K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14" ], "Z8K5": "Z48003" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "replace specific item's label in HTML fragment" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } trm9to3p68oulap5bprtmylwxy8fc0f 334010 334009 2026-10-27T22:54:43Z ReXLer 39813 334010 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48003" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z48003K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6", "Z17K2": "Z48003K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "replacement label" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z48003K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z48003K4", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "HTML" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14" ], "Z8K5": "Z48003" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "replace specific item's label in HTML fragment" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 2a6dphfqqhibcnrf8sih0iytijzs2j3 334012 334010 2026-10-27T22:58:19Z ReXLer 39813 Added Z48004 to the approved list of implementations 334012 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48003" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z48003K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6", "Z17K2": "Z48003K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "replacement label" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z48003K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z48003K4", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "HTML" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14", "Z48004" ], "Z8K5": "Z48003" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "replace specific item's label in HTML fragment" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } p5zrk6nz4p0o7uejsbh7gxva8l8s5f1 334014 334012 2026-10-27T22:59:57Z ReXLer 39813 Removed Z48004 from the approved list of implementations 334014 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48003" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z48003K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6", "Z17K2": "Z48003K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "replacement label" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z48003K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z48003K4", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "HTML" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14" ], "Z8K5": "Z48003" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "replace specific item's label in HTML fragment" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 2a6dphfqqhibcnrf8sih0iytijzs2j3 334015 334014 2026-10-27T23:00:00Z ReXLer 39813 Added Z48004 to the approved list of implementations 334015 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48003" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z48003K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6", "Z17K2": "Z48003K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "replacement label" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z48003K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z48003K4", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "HTML" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14", "Z48004" ], "Z8K5": "Z48003" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "replace specific item's label in HTML fragment" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } p5zrk6nz4p0o7uejsbh7gxva8l8s5f1 334017 334015 2026-10-27T23:02:45Z ReXLer 39813 Removed Z48004 from the approved list of implementations 334017 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48003" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z48003K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6", "Z17K2": "Z48003K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "replacement label" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z48003K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z48003K4", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "HTML" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14" ], "Z8K5": "Z48003" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "replace specific item's label in HTML fragment" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 2a6dphfqqhibcnrf8sih0iytijzs2j3 334018 334017 2026-10-27T23:02:48Z ReXLer 39813 Added Z48004 to the approved list of implementations 334018 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48003" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z48003K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6", "Z17K2": "Z48003K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "replacement label" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z48003K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z48003K4", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "HTML" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14", "Z48004" ], "Z8K5": "Z48003" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "replace specific item's label in HTML fragment" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } p5zrk6nz4p0o7uejsbh7gxva8l8s5f1 334020 334018 2026-10-27T23:03:56Z ReXLer 39813 Added Z48005 to the approved list of test cases 334020 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48003" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z48003K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6", "Z17K2": "Z48003K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "replacement label" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z48003K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z48003K4", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "HTML" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20", "Z48005" ], "Z8K4": [ "Z14", "Z48004" ], "Z8K5": "Z48003" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "replace specific item's label in HTML fragment" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } laf46zexa9ido7n72zwvfag5rir2akd Z48004 0 101716 334011 2026-10-27T22:57:39Z ReXLer 39813 334011 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48004" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z48003", "Z14K2": { "Z1K1": "Z7", "Z7K1": "Z47997", "Z47997K1": { "Z1K1": "Z7", "Z7K1": "Z10075", "Z10075K1": { "Z1K1": "Z7", "Z7K1": "Z27854", "Z27854K1": { "Z1K1": "Z18", "Z18K1": "Z48003K4" } }, "Z10075K2": { "Z1K1": "Z7", "Z7K1": "Z27854", "Z27854K1": { "Z1K1": "Z7", "Z7K1": "Z32428", "Z32428K1": { "Z1K1": "Z18", "Z18K1": "Z48003K1" }, "Z32428K2": { "Z1K1": "Z18", "Z18K1": "Z48003K3" } } }, "Z10075K3": { "Z1K1": "Z7", "Z7K1": "Z27854", "Z27854K1": { "Z1K1": "Z7", "Z7K1": "Z43477", "Z43477K1": "a", "Z43477K2": "href", "Z43477K3": [ "Z6", "https://abstract.wikipedia.org/wiki/", { "Z1K1": "Z7", "Z7K1": "Z20041", "Z20041K1": { "Z1K1": "Z18", "Z18K1": "Z48003K1" } } ], "Z43477K4": { "Z1K1": "Z18", "Z18K1": "Z48003K2" } } } } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "replace specific item's label, comp" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 4mqbd09419jxsf29c5r8sxflexxk4kj 334013 334011 2026-10-27T22:59:45Z ReXLer 39813 fix 334013 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48004" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z48003", "Z14K2": { "Z1K1": "Z7", "Z7K1": "Z47997", "Z47997K1": { "Z1K1": "Z7", "Z7K1": "Z10075", "Z10075K1": { "Z1K1": "Z7", "Z7K1": "Z27854", "Z27854K1": { "Z1K1": "Z18", "Z18K1": "Z48003K4" } }, "Z10075K2": { "Z1K1": "Z7", "Z7K1": "Z27854", "Z27854K1": { "Z1K1": "Z7", "Z7K1": "Z32428", "Z32428K1": { "Z1K1": "Z18", "Z18K1": "Z48003K1" }, "Z32428K2": { "Z1K1": "Z18", "Z18K1": "Z48003K3" } } }, "Z10075K3": { "Z1K1": "Z7", "Z7K1": "Z27854", "Z27854K1": { "Z1K1": "Z7", "Z7K1": "Z43477", "Z43477K1": "a", "Z43477K2": "href", "Z43477K3": [ "Z6", { "Z1K1": "Z7", "Z7K1": "Z21394", "Z21394K1": [ "Z6", "https://abstract.wikipedia.org/wiki/", { "Z1K1": "Z7", "Z7K1": "Z20041", "Z20041K1": { "Z1K1": "Z18", "Z18K1": "Z48003K1" } } ] } ], "Z43477K4": { "Z1K1": "Z18", "Z18K1": "Z48003K2" } } } } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "replace specific item's label, comp" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } f5cdtpu2n7m1c6bbvl0uo85mhmhrc74 334016 334013 2026-10-27T23:02:43Z ReXLer 39813 this should fix it 334016 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48004" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z48003", "Z14K2": { "Z1K1": "Z7", "Z7K1": "Z47997", "Z47997K1": { "Z1K1": "Z7", "Z7K1": "Z10075", "Z10075K1": { "Z1K1": "Z7", "Z7K1": "Z27854", "Z27854K1": { "Z1K1": "Z18", "Z18K1": "Z48003K4" } }, "Z10075K2": { "Z1K1": "Z7", "Z7K1": "Z27854", "Z27854K1": { "Z1K1": "Z7", "Z7K1": "Z32428", "Z32428K1": { "Z1K1": "Z18", "Z18K1": "Z48003K1" }, "Z32428K2": { "Z1K1": "Z18", "Z18K1": "Z48003K3" } } }, "Z10075K3": { "Z1K1": "Z7", "Z7K1": "Z27854", "Z27854K1": { "Z1K1": "Z7", "Z7K1": "Z27926", "Z27926K1": [ "Z89", { "Z1K1": "Z89", "Z89K1": "\u003Ca href=\"https://abstract.wikipedia.org/wiki/" }, { "Z1K1": "Z7", "Z7K1": "Z47997", "Z47997K1": { "Z1K1": "Z7", "Z7K1": "Z20041", "Z20041K1": { "Z1K1": "Z18", "Z18K1": "Z48003K1" } } }, { "Z1K1": "Z89", "Z89K1": "\"\u003E" }, { "Z1K1": "Z7", "Z7K1": "Z27868", "Z27868K1": { "Z1K1": "Z18", "Z18K1": "Z48003K2" } }, { "Z1K1": "Z89", "Z89K1": "\u003C/a\u003E" } ] } } } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "replace specific item's label, comp" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } sawykfb52irgydzxnkr4icbyzypae4z Z48005 0 101717 334019 2026-10-27T23:03:32Z ReXLer 39813 334019 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48005" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z48003", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z48003", "Z48003K1": { "Z1K1": "Z6091", "Z6091K1": "Q80955" }, "Z48003K2": "Santos FC", "Z48003K3": "Z1002", "Z48003K4": { "Z1K1": "Z7", "Z7K1": "Z32428", "Z32428K1": { "Z1K1": "Z6091", "Z6091K1": "Q80955" }, "Z32428K2": "Z1002" } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z877", "Z877K2": { "Z1K1": "Z89", "Z89K1": "\u003Ca href=\"https://abstract.wikipedia.org/wiki/Q80955\"\u003ESantos FC\u003C/a\u003E" } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Santos F.C. -\u003E Santos FC" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 5rnadvlmva8t844sfdhmy4wei9lqx0d Z48006 0 101718 334022 2026-10-28T06:56:13Z Jsamwrites 938 Create Follows sentence, French: June 334022 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48006" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47282", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47282", "Z47282K1": { "Z1K1": "Z6091", "Z6091K1": "Q120" }, "Z47282K2": { "Z1K1": "Z60", "Z60K1": "fr" }, "Z47282K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "Juin suit mai." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Follows sentence, French: June" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } t5xz5oyjxbcpuhgh1oqihk0etifha40 Z48007 0 101719 334023 2026-10-28T06:56:16Z Jsamwrites 938 Create Follows sentence, Spanish: June 334023 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48007" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47282", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47282", "Z47282K1": { "Z1K1": "Z6091", "Z6091K1": "Q120" }, "Z47282K2": { "Z1K1": "Z60", "Z60K1": "es" }, "Z47282K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "Junio sigue mayo." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Follows sentence, Spanish: June" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } im6az60qlsjhqqkwm7fmbtp06dkd4t4 Z48008 0 101720 334024 2026-10-28T06:56:18Z Jsamwrites 938 Create Followed by sentence, English: June 334024 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48008" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47284", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47284", "Z47284K1": { "Z1K1": "Z6091", "Z6091K1": "Q120" }, "Z47284K2": { "Z1K1": "Z60", "Z60K1": "en" }, "Z47284K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "June is followed by July." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Followed by sentence, English: June" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } 8eupaeqvjvyt2ytgz899yq63v7o53au Z48009 0 101721 334025 2026-10-28T06:56:20Z Jsamwrites 938 Create Followed by sentence, French: June 334025 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48009" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47284", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47284", "Z47284K1": { "Z1K1": "Z6091", "Z6091K1": "Q120" }, "Z47284K2": { "Z1K1": "Z60", "Z60K1": "fr" }, "Z47284K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "Juin est suivi par juillet." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Followed by sentence, French: June" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } sz1h8oysqkyk4ytbfygjz7weh9465rb Z48010 0 101722 334026 2026-10-28T06:56:22Z Jsamwrites 938 Create Followed by sentence, Spanish: June 334026 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48010" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z47284", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z11K2" }, "Z803K2": { "Z1K1": "Z7", "Z7K1": "Z47284", "Z47284K1": { "Z1K1": "Z6091", "Z6091K1": "Q120" }, "Z47284K2": { "Z1K1": "Z60", "Z60K1": "es" }, "Z47284K3": [ "Z39328" ] } }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z866", "Z866K2": "Junio es seguido por julio." } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Followed by sentence, Spanish: June" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11" ] } } ieedut9zle49fk5ugrewu86bomx0oyb Z48011 0 101723 334031 2026-10-28T07:24:47Z Jsamwrites 938 Create Image thumbnail with alt text and caption 334031 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48011" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z310", "Z17K2": "Z48011K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "image" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6", "Z17K2": "Z48011K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "alternative text" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z48011K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "caption" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z48011K4", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "caption language" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14" ], "Z8K5": "Z48011" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Image thumbnail with alt text and caption" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Renders a Commons thumbnail with independent alternative text and a language-tagged visible caption." } ] } } 5uzyi6kyjfyp7cs42htaiiv4uk71haw 334039 334031 2026-10-28T07:26:48Z Jsamwrites 938 Added Z48013 to the approved list of implementations 334039 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48011" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z310", "Z17K2": "Z48011K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "image" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6", "Z17K2": "Z48011K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "alternative text" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z48011K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "caption" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z48011K4", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "caption language" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14", "Z48013" ], "Z8K5": "Z48011" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Image thumbnail with alt text and caption" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Renders a Commons thumbnail with independent alternative text and a language-tagged visible caption." } ] } } t0sxjb968oivqovrjzr9gnvv9dypvo6 334040 334039 2026-10-28T07:26:51Z Jsamwrites 938 Added Z48014 and Z48015 to the approved list of test cases 334040 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48011" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z310", "Z17K2": "Z48011K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "image" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6", "Z17K2": "Z48011K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "alternative text" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z48011K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "caption" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z48011K4", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "caption language" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20", "Z48014", "Z48015" ], "Z8K4": [ "Z14", "Z48013" ], "Z8K5": "Z48011" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Image thumbnail with alt text and caption" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Renders a Commons thumbnail with independent alternative text and a language-tagged visible caption." } ] } } tuk7q0qxnrk0xsgdfts8adl21i70uep 334048 334040 2026-10-28T08:12:19Z Jsamwrites 938 Removed Z48013 from the approved list of implementations 334048 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48011" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z310", "Z17K2": "Z48011K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "image" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6", "Z17K2": "Z48011K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "alternative text" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z48011K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "caption" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z48011K4", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "caption language" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20", "Z48014", "Z48015" ], "Z8K4": [ "Z14" ], "Z8K5": "Z48011" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Image thumbnail with alt text and caption" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Renders a Commons thumbnail with independent alternative text and a language-tagged visible caption." } ] } } 43dvmxqdc7nrsnnvpl32mnlm8fp9nzu 334049 334048 2026-10-28T08:12:25Z Jsamwrites 938 Removed Z48014 and Z48015 from the approved list of test cases 334049 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48011" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z310", "Z17K2": "Z48011K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "image" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6", "Z17K2": "Z48011K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "alternative text" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z48011K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "caption" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z48011K4", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "caption language" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14" ], "Z8K5": "Z48011" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Image thumbnail with alt text and caption" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Renders a Commons thumbnail with independent alternative text and a language-tagged visible caption." } ] } } 5uzyi6kyjfyp7cs42htaiiv4uk71haw 334053 334049 2026-10-28T08:13:27Z Jsamwrites 938 Added Z48013 to the approved list of implementations 334053 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48011" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z310", "Z17K2": "Z48011K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "image" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6", "Z17K2": "Z48011K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "alternative text" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z48011K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "caption" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z48011K4", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "caption language" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14", "Z48013" ], "Z8K5": "Z48011" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Image thumbnail with alt text and caption" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Renders a Commons thumbnail with independent alternative text and a language-tagged visible caption." } ] } } t0sxjb968oivqovrjzr9gnvv9dypvo6 334054 334053 2026-10-28T08:13:31Z Jsamwrites 938 Added Z48014 and Z48015 to the approved list of test cases 334054 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48011" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z310", "Z17K2": "Z48011K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "image" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6", "Z17K2": "Z48011K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "alternative text" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z48011K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "caption" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z48011K4", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "caption language" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20", "Z48014", "Z48015" ], "Z8K4": [ "Z14", "Z48013" ], "Z8K5": "Z48011" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Image thumbnail with alt text and caption" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Renders a Commons thumbnail with independent alternative text and a language-tagged visible caption." } ] } } tuk7q0qxnrk0xsgdfts8adl21i70uep Z48012 0 101724 334032 2026-10-28T07:24:50Z Jsamwrites 938 Create Image thumbnail with QID alt text and caption 334032 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48012" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z310", "Z17K2": "Z48012K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "image" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z48012K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item QID used to construct alt text" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z48012K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "caption" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z48012K4", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14" ], "Z8K5": "Z48012" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Image thumbnail with QID alt text and caption" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Renders a captioned Commons thumbnail and derives independent alt text from a Wikidata item and language." } ] } } hm82spc7wuygcd2tvybzhyi3v2uks9e 334041 334032 2026-10-28T07:28:00Z Jsamwrites 938 Added Z48016 to the approved list of implementations 334041 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48012" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z310", "Z17K2": "Z48012K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "image" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z48012K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item QID used to construct alt text" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z48012K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "caption" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z48012K4", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14", "Z48016" ], "Z8K5": "Z48012" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Image thumbnail with QID alt text and caption" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Renders a captioned Commons thumbnail and derives independent alt text from a Wikidata item and language." } ] } } k2nk3cnqu32ndc6jirp1tyqvtp1spgh 334042 334041 2026-10-28T07:28:03Z Jsamwrites 938 Added Z48017 to the approved list of test cases 334042 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48012" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z310", "Z17K2": "Z48012K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "image" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z48012K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item QID used to construct alt text" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z89", "Z17K2": "Z48012K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "caption" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z48012K4", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20", "Z48017" ], "Z8K4": [ "Z14", "Z48016" ], "Z8K5": "Z48012" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Image thumbnail with QID alt text and caption" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Renders a captioned Commons thumbnail and derives independent alt text from a Wikidata item and language." } ] } } kxmhr4lkpkhhou9kadp17tk7h0nhtgd Z48013 0 101725 334033 2026-10-28T07:24:53Z Jsamwrites 938 Create composition implementation of Image thumbnail with alt text and caption 334033 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48013" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z48011", "Z14K2": { "Z1K1": "Z7", "Z7K1": "Z27873", "Z27873K1": { "Z1K1": "Z7", "Z7K1": "Z27926", "Z27926K1": [ "Z89", { "Z1K1": "Z7", "Z7K1": "Z36038", "Z36038K1": { "Z1K1": "Z18", "Z18K1": "Z48011K1" }, "Z36038K2": { "Z1K1": "Z18", "Z18K1": "Z48011K2" } }, { "Z1K1": "Z7", "Z7K1": "Z27873", "Z27873K1": { "Z1K1": "Z18", "Z18K1": "Z48011K3" }, "Z27873K2": "p", "Z27873K3": [ "Z6", "class", "lang" ], "Z27873K4": [ "Z6", "ext-wikilambda-image-caption", { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z60K1" }, "Z803K2": { "Z1K1": "Z18", "Z18K1": "Z48011K4" } } ] } ] }, "Z27873K2": "div", "Z27873K3": [ "Z6", "class" ], "Z27873K4": [ "Z6", "ext-wikilambda-captioned-image" ] } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Image thumbnail with alt text and caption, composition" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Composes the established thumbnail, HTML join and safe tag-wrapping functions." } ] } } l6ylbnw99j5wjedoir28bs3new2in8g 334050 334033 2026-10-28T08:13:02Z Jsamwrites 938 Keep the generated image float with its cleared caption 334050 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48013" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z48011", "Z14K2": { "Z1K1": "Z7", "Z7K1": "Z27873", "Z27873K1": { "Z1K1": "Z7", "Z7K1": "Z27926", "Z27926K1": [ "Z89", { "Z1K1": "Z7", "Z7K1": "Z36038", "Z36038K1": { "Z1K1": "Z18", "Z18K1": "Z48011K1" }, "Z36038K2": { "Z1K1": "Z18", "Z18K1": "Z48011K2" } }, { "Z1K1": "Z7", "Z7K1": "Z27873", "Z27873K1": { "Z1K1": "Z18", "Z18K1": "Z48011K3" }, "Z27873K2": "p", "Z27873K3": [ "Z6", "class", "lang", "style" ], "Z27873K4": [ "Z6", "ext-wikilambda-image-caption", { "Z1K1": "Z7", "Z7K1": "Z803", "Z803K1": { "Z1K1": "Z39", "Z39K1": "Z60K1" }, "Z803K2": { "Z1K1": "Z18", "Z18K1": "Z48011K4" } }, "clear: both; text-align: center; margin-block-start: 0.25em;" ] } ] }, "Z27873K2": "div", "Z27873K3": [ "Z6", "class", "style" ], "Z27873K4": [ "Z6", "ext-wikilambda-captioned-image", "display: flow-root; width: fit-content;" ] } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Image thumbnail with alt text and caption, composition" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Composes the established thumbnail, HTML join and safe tag-wrapping functions." } ] } } 85yvujhqdqd3xxp4cye1ny9o9l3yjq4 Z48014 0 101726 334034 2026-10-28T07:24:56Z Jsamwrites 938 Create native captioned-image test 334034 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48014" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z48011", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z48011", "Z48011K1": { "Z1K1": "Z310", "Z310K1": "M33189266" }, "Z48011K2": "Universe", "Z48011K3": { "Z1K1": "Z89", "Z89K1": "Hubble Ultra Deep Field 2014" }, "Z48011K4": "Z1002" }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z877", "Z877K2": { "Z1K1": "Z89", "Z89K1": "\u003Cdiv class=\"ext-wikilambda-captioned-image\"\u003E\u003Cext-wikilambda-image mid=\"M33189266\" alt=\"Universe\" size=\"thumb\" /\u003E\u003Cp class=\"ext-wikilambda-image-caption\" lang=\"en\"\u003EHubble Ultra Deep Field 2014\u003C/p\u003E\u003C/div\u003E" } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Image thumbnail with alt text and caption: Hubble Ultra Deep Field, English" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Checks the exact accessible image and caption HTML fragment." } ] } } oihyqkv0e3ijtucilq5cp7htl6vnl4f 334051 334034 2026-10-28T08:13:05Z Jsamwrites 938 Update expected caption layout with float containment 334051 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48014" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z48011", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z48011", "Z48011K1": { "Z1K1": "Z310", "Z310K1": "M33189266" }, "Z48011K2": "Universe", "Z48011K3": { "Z1K1": "Z89", "Z89K1": "Hubble Ultra Deep Field 2014" }, "Z48011K4": "Z1002" }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z877", "Z877K2": { "Z1K1": "Z89", "Z89K1": "\u003Cdiv class=\"ext-wikilambda-captioned-image\" style=\"display: flow-root; width: fit-content;\"\u003E\u003Cext-wikilambda-image mid=\"M33189266\" alt=\"Universe\" size=\"thumb\" /\u003E\u003Cp class=\"ext-wikilambda-image-caption\" lang=\"en\" style=\"clear: both; text-align: center; margin-block-start: 0.25em;\"\u003EHubble Ultra Deep Field 2014\u003C/p\u003E\u003C/div\u003E" } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Image thumbnail with alt text and caption: Hubble Ultra Deep Field, English" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Checks the exact accessible image and caption HTML fragment." } ] } } hvcmcgtp43c9hsgik2o9z6cepm8eoiw Z48015 0 101727 334035 2026-10-28T07:24:59Z Jsamwrites 938 Create native captioned-image test 334035 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48015" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z48011", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z48011", "Z48011K1": { "Z1K1": "Z310", "Z310K1": "M33189266" }, "Z48011K2": "Univers", "Z48011K3": { "Z1K1": "Z89", "Z89K1": "Champ ultra-profond de Hubble 2014" }, "Z48011K4": "Z1004" }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z877", "Z877K2": { "Z1K1": "Z89", "Z89K1": "\u003Cdiv class=\"ext-wikilambda-captioned-image\"\u003E\u003Cext-wikilambda-image mid=\"M33189266\" alt=\"Univers\" size=\"thumb\" /\u003E\u003Cp class=\"ext-wikilambda-image-caption\" lang=\"fr\"\u003EChamp ultra-profond de Hubble 2014\u003C/p\u003E\u003C/div\u003E" } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Image thumbnail with alt text and caption: Hubble Ultra Deep Field, French" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Checks the exact accessible image and caption HTML fragment." } ] } } 6dbblg8tsszqahi5m6t3vuzj9k3wl1z 334052 334035 2026-10-28T08:13:08Z Jsamwrites 938 Update expected caption layout with float containment 334052 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48015" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z48011", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z48011", "Z48011K1": { "Z1K1": "Z310", "Z310K1": "M33189266" }, "Z48011K2": "Univers", "Z48011K3": { "Z1K1": "Z89", "Z89K1": "Champ ultra-profond de Hubble 2014" }, "Z48011K4": "Z1004" }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z877", "Z877K2": { "Z1K1": "Z89", "Z89K1": "\u003Cdiv class=\"ext-wikilambda-captioned-image\" style=\"display: flow-root; width: fit-content;\"\u003E\u003Cext-wikilambda-image mid=\"M33189266\" alt=\"Univers\" size=\"thumb\" /\u003E\u003Cp class=\"ext-wikilambda-image-caption\" lang=\"fr\" style=\"clear: both; text-align: center; margin-block-start: 0.25em;\"\u003EChamp ultra-profond de Hubble 2014\u003C/p\u003E\u003C/div\u003E" } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Image thumbnail with alt text and caption: Hubble Ultra Deep Field, French" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Checks the exact accessible image and caption HTML fragment." } ] } } 5le9x54i251uems1isd4hodtbi8rirk Z48016 0 101728 334036 2026-10-28T07:25:02Z Jsamwrites 938 Create composition implementation of Image thumbnail with QID alt text and caption 334036 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48016" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z48012", "Z14K2": { "Z1K1": "Z7", "Z7K1": "Z48011", "Z48011K1": { "Z1K1": "Z18", "Z18K1": "Z48012K1" }, "Z48011K2": { "Z1K1": "Z7", "Z7K1": "Z36270", "Z36270K1": { "Z1K1": "Z18", "Z18K1": "Z48012K2" }, "Z36270K2": { "Z1K1": "Z18", "Z18K1": "Z48012K4" } }, "Z48011K3": { "Z1K1": "Z18", "Z18K1": "Z48012K3" }, "Z48011K4": { "Z1K1": "Z18", "Z18K1": "Z48012K4" } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Image thumbnail with QID alt text and caption, composition" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Reuses the captioned-image renderer and the same QID-to-alt-text function used by Z38053." } ] } } 6d2puq6crxpeca7ffd416o55fokm4cr Z48017 0 101729 334037 2026-10-28T07:25:05Z Jsamwrites 938 Create native captioned-image test 334037 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48017" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z48012", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z48012", "Z48012K1": { "Z1K1": "Z310", "Z310K1": "M33189266" }, "Z48012K2": { "Z1K1": "Z6091", "Z6091K1": "Q1" }, "Z48012K3": { "Z1K1": "Z89", "Z89K1": "Hubble Ultra Deep Field 2014" }, "Z48012K4": "Z1002" }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z877", "Z877K2": { "Z1K1": "Z89", "Z89K1": "\u003Cdiv class=\"ext-wikilambda-captioned-image\"\u003E\u003Cext-wikilambda-image mid=\"M33189266\" alt=\"Universe\" size=\"thumb\" /\u003E\u003Cp class=\"ext-wikilambda-image-caption\" lang=\"en\"\u003EHubble Ultra Deep Field 2014\u003C/p\u003E\u003C/div\u003E" } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Image thumbnail with QID alt text and caption: universe, English" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Checks the exact accessible image and caption HTML fragment." } ] } } 8psp22ar1xp31iz2eybmlpeqei6gyfr 334038 334037 2026-10-28T07:26:19Z Jsamwrites 938 Correct Q1 English alt-text expectation to lowercase universe 334038 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48017" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z48012", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z48012", "Z48012K1": { "Z1K1": "Z310", "Z310K1": "M33189266" }, "Z48012K2": { "Z1K1": "Z6091", "Z6091K1": "Q1" }, "Z48012K3": { "Z1K1": "Z89", "Z89K1": "Hubble Ultra Deep Field 2014" }, "Z48012K4": "Z1002" }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z877", "Z877K2": { "Z1K1": "Z89", "Z89K1": "\u003Cdiv class=\"ext-wikilambda-captioned-image\"\u003E\u003Cext-wikilambda-image mid=\"M33189266\" alt=\"universe\" size=\"thumb\" /\u003E\u003Cp class=\"ext-wikilambda-image-caption\" lang=\"en\"\u003EHubble Ultra Deep Field 2014\u003C/p\u003E\u003C/div\u003E" } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Image thumbnail with QID alt text and caption: universe, English" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Checks the exact accessible image and caption HTML fragment." } ] } } tw8yqqldfe8g556efp5fxni3ufrawmb Z48018 0 101730 334043 2026-10-28T07:31:00Z Jsamwrites 938 Create Image thumbnail with QID alt text and QID caption 334043 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48018" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z310", "Z17K2": "Z48018K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "image" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z48018K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item QID used to construct alt text" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z48018K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item QID used to construct caption" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z48018K4", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14" ], "Z8K5": "Z48018" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Image thumbnail with QID alt text and QID caption" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Renders a captioned Commons thumbnail, deriving independent alt text and a visible caption from QIDs." } ] } } nskphrm0e5pp8tqeclbwmu83tadfuh4 334046 334043 2026-10-28T07:31:38Z Jsamwrites 938 Added Z48019 to the approved list of implementations 334046 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48018" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z310", "Z17K2": "Z48018K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "image" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z48018K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item QID used to construct alt text" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z48018K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item QID used to construct caption" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z48018K4", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14", "Z48019" ], "Z8K5": "Z48018" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Image thumbnail with QID alt text and QID caption" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Renders a captioned Commons thumbnail, deriving independent alt text and a visible caption from QIDs." } ] } } 2r9s0fyfkfnapvjs1jetvd9mfpietuw 334047 334046 2026-10-28T07:31:42Z Jsamwrites 938 Added Z48020 to the approved list of test cases 334047 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48018" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": "Z310", "Z17K2": "Z48018K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "image" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z48018K2", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item QID used to construct alt text" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z6091", "Z17K2": "Z48018K3", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "item QID used to construct caption" } ] } }, { "Z1K1": "Z17", "Z17K1": "Z60", "Z17K2": "Z48018K4", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "language" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20", "Z48020" ], "Z8K4": [ "Z14", "Z48019" ], "Z8K5": "Z48018" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Image thumbnail with QID alt text and QID caption" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Renders a captioned Commons thumbnail, deriving independent alt text and a visible caption from QIDs." } ] } } 5pqe5ctcop55vezzo199eo4tty5f48k Z48019 0 101731 334044 2026-10-28T07:31:03Z Jsamwrites 938 Create composition implementation of Image thumbnail with QID alt text and QID caption 334044 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48019" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z48018", "Z14K2": { "Z1K1": "Z7", "Z7K1": "Z48012", "Z48012K1": { "Z1K1": "Z18", "Z18K1": "Z48018K1" }, "Z48012K2": { "Z1K1": "Z18", "Z18K1": "Z48018K2" }, "Z48012K3": { "Z1K1": "Z7", "Z7K1": "Z27868", "Z27868K1": { "Z1K1": "Z7", "Z7K1": "Z14396", "Z14396K1": { "Z1K1": "Z7", "Z7K1": "Z31676", "Z31676K1": { "Z1K1": "Z18", "Z18K1": "Z48018K3" }, "Z31676K2": { "Z1K1": "Z18", "Z18K1": "Z48018K4" } } } }, "Z48012K4": { "Z1K1": "Z18", "Z18K1": "Z48018K4" } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Image thumbnail with QID alt text and QID caption, composition" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Resolves and escapes the localized caption label, then delegates to the QID-alt captioned-image function." } ] } } 1d49imx7nnth8hix2qs4mk683kjzipy Z48020 0 101732 334045 2026-10-28T07:31:06Z Jsamwrites 938 Create native QID-captioned-image test 334045 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48020" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z48018", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z48018", "Z48018K1": { "Z1K1": "Z310", "Z310K1": "M33189266" }, "Z48018K2": { "Z1K1": "Z6091", "Z6091K1": "Q1" }, "Z48018K3": { "Z1K1": "Z6091", "Z6091K1": "Q1" }, "Z48018K4": "Z1002" }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z877", "Z877K2": { "Z1K1": "Z89", "Z89K1": "\u003Cdiv class=\"ext-wikilambda-captioned-image\"\u003E\u003Cext-wikilambda-image mid=\"M33189266\" alt=\"universe\" size=\"thumb\" /\u003E\u003Cp class=\"ext-wikilambda-image-caption\" lang=\"en\"\u003Euniverse\u003C/p\u003E\u003C/div\u003E" } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Image thumbnail with QID alt text and QID caption: universe image and caption, English" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Checks the exact accessible image and caption HTML fragment." } ] } } 7suxcpikkq89ld3pwh5s0g105t2rqtx Z48021 0 101733 334055 2026-10-28T08:27:59Z Jsamwrites 938 Create Gallery from captioned image fragments 334055 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48021" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": { "Z1K1": "Z7", "Z7K1": "Z881", "Z881K1": "Z89" }, "Z17K2": "Z48021K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "captioned image fragments" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14" ], "Z8K5": "Z48021" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Gallery from captioned image fragments" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Places captioned image fragments in a responsive wrapping gallery container." } ] } } opx6yy1s0pvadzqlrhbqvo0dov961yz 334059 334055 2026-10-28T08:28:17Z Jsamwrites 938 Added Z48022 to the approved list of implementations 334059 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48021" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": { "Z1K1": "Z7", "Z7K1": "Z881", "Z881K1": "Z89" }, "Z17K2": "Z48021K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "captioned image fragments" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20" ], "Z8K4": [ "Z14", "Z48022" ], "Z8K5": "Z48021" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Gallery from captioned image fragments" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Places captioned image fragments in a responsive wrapping gallery container." } ] } } 14cg8f21sbvon6q0wwlhy43hau14gid 334060 334059 2026-10-28T08:28:21Z Jsamwrites 938 Added Z48023 and Z48024 to the approved list of test cases 334060 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48021" }, "Z2K2": { "Z1K1": "Z8", "Z8K1": [ "Z17", { "Z1K1": "Z17", "Z17K1": { "Z1K1": "Z7", "Z7K1": "Z881", "Z881K1": "Z89" }, "Z17K2": "Z48021K1", "Z17K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "captioned image fragments" } ] } } ], "Z8K2": "Z89", "Z8K3": [ "Z20", "Z48023", "Z48024" ], "Z8K4": [ "Z14", "Z48022" ], "Z8K5": "Z48021" }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Gallery from captioned image fragments" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Places captioned image fragments in a responsive wrapping gallery container." } ] } } e8t7rzeisrlxre54338nsoxb4w2g06o Z48022 0 101734 334056 2026-10-28T08:28:02Z Jsamwrites 938 Create composition implementation of Gallery from captioned image fragments 334056 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48022" }, "Z2K2": { "Z1K1": "Z14", "Z14K1": "Z48021", "Z14K2": { "Z1K1": "Z7", "Z7K1": "Z27873", "Z27873K1": { "Z1K1": "Z7", "Z7K1": "Z27926", "Z27926K1": { "Z1K1": "Z18", "Z18K1": "Z48021K1" } }, "Z27873K2": "div", "Z27873K3": [ "Z6", "class", "style" ], "Z27873K4": [ "Z6", "ext-wikilambda-image-gallery", "display: flex; flex-wrap: wrap; align-items: flex-start; gap: 1em;" ] } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Gallery from captioned image fragments, composition" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Joins the supplied HTML fragments and wraps them in a responsive flex container." } ] } } 7oeja0per39b8gew5fb088qkdrxoylx Z48023 0 101735 334057 2026-10-28T08:28:05Z Jsamwrites 938 Create native gallery-container test 334057 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48023" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z48021", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z48021", "Z48021K1": [ "Z89", { "Z1K1": "Z89", "Z89K1": "first" }, { "Z1K1": "Z89", "Z89K1": "second" } ] }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z877", "Z877K2": { "Z1K1": "Z89", "Z89K1": "\u003Cdiv class=\"ext-wikilambda-image-gallery\" style=\"display: flex; flex-wrap: wrap; align-items: flex-start; gap: 1em;\"\u003Efirstsecond\u003C/div\u003E" } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Gallery from captioned image fragments: two fragments" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Checks the exact responsive gallery HTML fragment." } ] } } b6oj9z3hbmjftb8dusn816qbw81cfej Z48024 0 101736 334058 2026-10-28T08:28:07Z Jsamwrites 938 Create native gallery-container test 334058 zobject text/plain { "Z1K1": "Z2", "Z2K1": { "Z1K1": "Z6", "Z6K1": "Z48024" }, "Z2K2": { "Z1K1": "Z20", "Z20K1": "Z48021", "Z20K2": { "Z1K1": "Z7", "Z7K1": "Z48021", "Z48021K1": [ "Z89" ] }, "Z20K3": { "Z1K1": "Z7", "Z7K1": "Z877", "Z877K2": { "Z1K1": "Z89", "Z89K1": "\u003Cdiv class=\"ext-wikilambda-image-gallery\" style=\"display: flex; flex-wrap: wrap; align-items: flex-start; gap: 1em;\"\u003E\u003C/div\u003E" } } }, "Z2K3": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Gallery from captioned image fragments: empty gallery" } ] }, "Z2K4": { "Z1K1": "Z32", "Z32K1": [ "Z31" ] }, "Z2K5": { "Z1K1": "Z12", "Z12K1": [ "Z11", { "Z1K1": "Z11", "Z11K1": "Z1002", "Z11K2": "Checks the exact responsive gallery HTML fragment." } ] } } iptt5sjp7vdiqltxk5bxhllfnekw7vc