with one click
develop-import-translator
// Develop an import translator that parses a file format (JSON, XML, RIS, BibTeX, CSV, etc.) into Zotero items.
// Develop an import translator that parses a file format (JSON, XML, RIS, BibTeX, CSV, etc.) into Zotero items.
Analyze a website's API by capturing network traffic (HAR) and generating an OpenAPI spec via mitmproxy2swagger.
Create or update test cases for a Zotero translator by running it against live URLs and capturing the output.
Develop an export translator that converts Zotero items into a file format (JSON, XML, CSV, etc.).
Develop a search translator that looks up items by identifier (DOI, ISBN, PMID, arXiv ID, etc.) via an external API. NOT for websites with search pages — use develop-web-translator for those.
Develop a web translator that scrapes bibliographic data from a website. This is the most common translator type.
Inspect a live web page using headless Chrome. Gets screenshots, meta tags, accessibility tree, and runs CSS selectors or JS expressions against the rendered DOM.
| name | develop-import-translator |
| description | Develop an import translator that parses a file format (JSON, XML, RIS, BibTeX, CSV, etc.) into Zotero items. |
Fetch and read the Zotero translator documentation:
Also read index.d.ts for type definitions.
Look for existing import translators that handle similar formats:
grep -l "detectImport\|doImport" *.js
node .bin/init-translator.mjs --label "<Label>" --creator "<Creator>" --type import
If the translator should also export the same format, use --type import,export and implement doExport() as described in the develop-export-translator skill.
Import translators have no target regex — they match on content via detectImport().
detectImport()Read the first few lines with Zotero.read() and return true if the format matches. Be specific to avoid false positives with other formats.
function detectImport() {
let start = '';
for (let i = 0; i < 10; i++) {
let line = Zotero.read();
if (line === false) break;
start += line;
}
// Check for a distinctive marker in the format
return start.includes('"my_format_version"');
}
doImport()Read the full input, parse it, and create items.
async function doImport() {
// Read all input
let text = '';
let line;
while ((line = Zotero.read()) !== false) {
text += line;
}
let data = JSON.parse(text);
for (let record of data.records) {
let item = new Zotero.Item('journalArticle');
item.title = record.title;
item.date = record.date;
for (let author of record.authors) {
item.creators.push({
firstName: author.first,
lastName: author.last,
creatorType: 'author',
});
}
// ... map other fields ...
item.complete();
}
}
Key APIs:
Zotero.read(length) — read characters from input. Returns false at EOF. With no argument, reads one line.new Zotero.Item(itemType) — create an item. Set fields as properties, then call .complete().(new DOMParser()).parseFromString(text, 'text/xml')node .bin/create-test.mjs "<Label>.js" --input '<paste example data here>'
Update lastUpdated every time you modify translator code.
node .bin/update-metadata.mjs "<Label>.js"
npm run lint -- "<Label>.js"
node .bin/run-tests.mjs "<Label>.js"