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—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><some function> returns never</q> as <q><some function> 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—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><some function> returns never</q> as <q><some function> 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—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