diff --git a/server.js b/server.js index da79478..d57f870 100644 --- a/server.js +++ b/server.js @@ -224,7 +224,18 @@ async function handleSaveGlossary(req, res, domainId, direction) { domains[domainId].glossaries[direction] = null; saveDomains(domains); } - return sendJson(res, createResp.status, { error: await forwardDeepLError(createResp) }); + const detail = await forwardDeepLError(createResp); + // DeepL answers 456 "Too many glossaries" once the account's glossary + // allowance is used up. On the API Free plan that allowance is a single + // glossary for the whole account, so this fires as soon as a second + // domain/direction is used - which reads like an app bug unless we say + // which glossary is holding the only slot. + if (createResp.status === 456 && /too many glossaries/i.test(detail)) { + return sendJson(res, 456, { + error: await describeGlossaryLimit(base, domainId, direction), + }); + } + return sendJson(res, createResp.status, { error: detail }); } const created = await createResp.json(); @@ -296,6 +307,33 @@ async function parseJsonBody(req) { } } +// Turns DeepL's bare "Too many glossaries" into something the person in the +// browser can act on: which glossaries already occupy the account's slots, +// and what the two ways out are. Falls back to a generic message if the +// account can't be listed for some reason. +async function describeGlossaryLimit(base, domainId, direction) { + const wanted = `${DOMAIN_LABELS[domainId]} (${GLOSSARY_DIRECTIONS[direction].label})`; + let inUse = []; + try { + const resp = await fetch(`${base}/v2/glossaries`, { + headers: { Authorization: `DeepL-Auth-Key ${DEEPL_API_KEY}` }, + }); + if (resp.ok) inUse = (await resp.json()).glossaries || []; + } catch (_) { + /* fall through to the generic wording below */ + } + const listed = inUse.length + ? ` Currently in use: ${inUse.map((g) => `"${g.name}"`).join(', ')}.` + : ''; + return ( + `Your DeepL plan's glossary limit is already reached, so the glossary for ` + + `${wanted} could not be created.${listed} ` + + `Delete a glossary you no longer need to free up a slot, or upgrade the ` + + `DeepL API plan (the Free plan allows only one glossary per account, ` + + `which is not enough for one glossary per domain and direction).` + ); +} + async function forwardDeepLError(resp) { let detail = ''; try {