Add CSL 1.0.2 locators and switch to CSL locales for localization

And move Page to middle of list, while still selecting by default

https://forums.zotero.org/discussion/comment/396602/#Comment_396602
This commit is contained in:
Dan Stillman 2022-07-09 01:00:07 -04:00
parent 2ff67c987e
commit 629892b0b8
7 changed files with 129 additions and 31 deletions

View file

@ -48,7 +48,7 @@ function AnnotationBox({ data }) {
<div className="title">{Zotero.getString('itemTypes.annotation')}</div> <div className="title">{Zotero.getString('itemTypes.annotation')}</div>
<div className="container"> <div className="container">
<div className="header"> <div className="header">
<div>{Zotero.getString('citation.locator.page')} {data.pageLabel}</div> <div>{Zotero.Cite.getLocatorString('page')} {data.pageLabel}</div>
</div> </div>
{data.text !== undefined {data.text !== undefined
? <div className="text" style={textStyle}>{data.text}</div> ? <div className="text" style={textStyle}>{data.text}</div>

View file

@ -113,9 +113,10 @@ var Zotero_Citation_Dialog = new function () {
var menu = document.getElementById("label"); var menu = document.getElementById("label");
var label_list = document.getElementById("locator-type-popup"); var label_list = document.getElementById("locator-type-popup");
var i = 0; var i = 0;
var pageLocatorIndex;
for(var value in locators) { for(var value in locators) {
var locator = locators[value]; var locator = locators[value];
var locatorLabel = Zotero.getString('citation.locator.'+locator.replace(/\s/g,'')); let locatorLabel = Zotero.Cite.getLocatorString(locator);
// add to list of labels // add to list of labels
var child = document.createElement("menuitem"); var child = document.createElement("menuitem");
child.setAttribute("value", value); child.setAttribute("value", value);
@ -124,9 +125,12 @@ var Zotero_Citation_Dialog = new function () {
// add to array // add to array
_locatorIndexArray[locator] = i; _locatorIndexArray[locator] = i;
_locatorNameArray[i] = locator; _locatorNameArray[i] = locator;
if (locator == 'page') {
pageLocatorIndex = i;
}
i++; i++;
} }
menu.selectedIndex = 0; menu.selectedIndex = pageLocatorIndex;
// load (from selectItemsDialog.js) // load (from selectItemsDialog.js)
yield doLoad(); yield doLoad();

View file

@ -116,10 +116,9 @@ var Zotero_QuickFormat = new function () {
// add labels to popup // add labels to popup
var locators = Zotero.Cite.labels; var locators = Zotero.Cite.labels;
var menu = document.getElementById("locator-label");
var labelList = document.getElementById("locator-label-popup"); var labelList = document.getElementById("locator-label-popup");
for(var locator of locators) { for(var locator of locators) {
var locatorLabel = Zotero.getString('citation.locator.'+locator.replace(/\s/g,'')); let locatorLabel = Zotero.Cite.getLocatorString(locator);
// add to list of labels // add to list of labels
var child = document.createElement("menuitem"); var child = document.createElement("menuitem");
@ -127,7 +126,6 @@ var Zotero_QuickFormat = new function () {
child.setAttribute("label", locatorLabel); child.setAttribute("label", locatorLabel);
labelList.appendChild(child); labelList.appendChild(child);
} }
menu.selectedIndex = 0;
} }
@ -1085,15 +1083,16 @@ var Zotero_QuickFormat = new function () {
let citationItem = JSON.parse(target.dataset.citationItem); let citationItem = JSON.parse(target.dataset.citationItem);
panelPrefix.value = citationItem["prefix"] ? citationItem["prefix"] : ""; panelPrefix.value = citationItem["prefix"] ? citationItem["prefix"] : "";
panelSuffix.value = citationItem["suffix"] ? citationItem["suffix"] : ""; panelSuffix.value = citationItem["suffix"] ? citationItem["suffix"] : "";
var pageOption = panelLocatorLabel.getElementsByAttribute("value", "page")[0];
if(citationItem["label"]) { if(citationItem["label"]) {
var option = panelLocatorLabel.getElementsByAttribute("value", citationItem["label"]); var option = panelLocatorLabel.getElementsByAttribute("value", citationItem["label"]);
if(option.length) { if(option.length) {
panelLocatorLabel.selectedItem = option[0]; panelLocatorLabel.selectedItem = option[0];
} else { } else {
panelLocatorLabel.selectedIndex = 0; panelLocatorLabel.selectedItem = pageOption;
} }
} else { } else {
panelLocatorLabel.selectedIndex = 0; panelLocatorLabel.selectedItem = pageOption;
} }
panelLocator.value = citationItem["locator"] ? citationItem["locator"] : ""; panelLocator.value = citationItem["locator"] ? citationItem["locator"] : "";
panelSuppressAuthor.checked = !!citationItem["suppress-author"]; panelSuppressAuthor.checked = !!citationItem["suppress-author"];

View file

@ -59,10 +59,8 @@ var Zotero_CSL_Editor = new function() {
var pageList = document.getElementById('zotero-csl-page-type'); var pageList = document.getElementById('zotero-csl-page-type');
var locators = Zotero.Cite.labels; var locators = Zotero.Cite.labels;
for (let type of locators) { for (let locator of locators) {
var locator = type; pageList.appendItem(Zotero.Cite.getLocatorString(locator), locator);
locator = Zotero.getString('citation.locator.'+locator.replace(/\s/g,''));
pageList.appendItem(locator, type);
} }
pageList.selectedIndex = 0; pageList.selectedIndex = 0;

View file

@ -8,9 +8,105 @@ Zotero.Cite = {
/** /**
* Locator labels * Locator labels
*/ */
"labels":["page", "book", "chapter", "column", "figure", "folio", "labels": [
"issue", "line", "note", "opus", "paragraph", "part", "section", "sub verbo", "act",
"volume", "verse"], "appendix",
"article-locator",
"book",
"canon",
"chapter",
"column",
"elocation",
"equation",
"figure",
"folio",
"issue",
"line",
"note",
"opus",
"page",
"paragraph",
"part",
"rule",
"scene",
"section",
"sub-verbo",
"table",
//"timestamp",
"title-locator",
"verse",
"volume"
],
_locatorStrings: new Map(),
/**
* Get localized string for locator
*
* @param {String} locator - Locator name (e.g., 'book')
* @return {String} - Localized string (e.g., 'Livre')
*/
getLocatorString: function (locator) {
// Get the best CSL locale for the current Zotero locale
var cslLocale = Zotero.Utilities.Internal.resolveLocale(
Zotero.locale,
Object.keys(Zotero.Styles.locales)
);
// If locator strings are already cached for the current locale, use that
if (this._locatorStrings.has(cslLocale)) {
return this._locatorStrings.get(cslLocale).get(locator);
}
var map = new Map();
this._locatorStrings.set(cslLocale, map);
var localeXML = Zotero.Cite.Locale.get(cslLocale);
var parser;
if (Zotero.platformMajorVersion > 60) {
parser = new DOMParser();
}
else {
parser = Components.classes["@mozilla.org/xmlextras/domparser;1"]
.createInstance(Components.interfaces.nsIDOMParser);
}
var doc = parser.parseFromString(localeXML, 'text/xml');
var englishDoc;
// Cache all locators for the current locale
for (let locator of this.labels) {
let elem = doc.querySelector(`term[name="${locator}"]:not([form="short"]) > single`);
if (!elem) {
// If locator not found, get from the U.S. English locale
if (cslLocale != 'en-US') {
Zotero.logError(`Locator '${locator}' not found in ${cslLocale} locale -- trying en-US`);
if (!englishDoc) {
englishDoc = parser.parseFromString(Zotero.Cite.Locale.get('en-US'), 'text/xml');
}
elem = englishDoc.querySelector(`term[name="${locator}"]:not([form="short"]) > single`);
if (!elem) {
Zotero.logError(`Locator '${locator}' not found in en-US locale -- using name`);
}
}
else {
Zotero.logError(`Locator '${locator}' not found in en-US locale -- using name`);
}
// If still not found, use the locator name directly
if (!elem) {
map.set(locator, Zotero.Utilities.capitalize(locator));
continue;
}
}
// If <single> is empty, use the locator name directly
let str = elem.textContent;
if (!str) {
Zotero.logError(`Locator '${locator}' is empty in ${cslLocale} locale -- using name`);
map.set(locator, Zotero.Utilities.capitalize(locator));
continue;
}
map.set(locator, Zotero.Utilities.capitalize(str));
}
return map.get(locator);
},
/** /**
* Remove specified item IDs in-place from a citeproc-js bibliography object returned * Remove specified item IDs in-place from a citeproc-js bibliography object returned

View file

@ -865,22 +865,6 @@ citation.showEditor = Show Editor…
citation.hideEditor = Hide Editor… citation.hideEditor = Hide Editor…
citation.citations = Citations citation.citations = Citations
citation.notes = Notes citation.notes = Notes
citation.locator.page = Page
citation.locator.book = Book
citation.locator.chapter = Chapter
citation.locator.column = Column
citation.locator.figure = Figure
citation.locator.folio = Folio
citation.locator.issue = Issue
citation.locator.line = Line
citation.locator.note = Note
citation.locator.opus = Opus
citation.locator.paragraph = Paragraph
citation.locator.part = Part
citation.locator.section = Section
citation.locator.subverbo = Sub verbo
citation.locator.volume = Volume
citation.locator.verse = Verse
report.title.default = Zotero Report report.title.default = Zotero Report
report.parentItem = Parent Item: report.parentItem = Parent Item:

View file

@ -1,4 +1,21 @@
describe("Zotero.Cite", function () { describe("Zotero.Cite", function () {
describe("#getLocatorString()", function () {
it("should get 'book' in en-US", function () {
Zotero.locale = 'en-US';
assert.equal(Zotero.Cite.getLocatorString('book'), 'Book');
});
it("should get 'sub-verbo' in en-US", function () {
Zotero.locale = 'en-US';
assert.equal(Zotero.Cite.getLocatorString('sub-verbo'), 'Sub verbo');
});
it("should get 'book' in fr-FR", function () {
Zotero.locale = 'fr-FR';
assert.equal(Zotero.Cite.getLocatorString('book'), 'Livre');
});
});
describe("#extraToCSL()", function () { describe("#extraToCSL()", function () {
it("should convert Extra field values to the more restrictive citeproc-js cheater syntax", function () { it("should convert Extra field values to the more restrictive citeproc-js cheater syntax", function () {
var str1 = 'Original Date: 2017\n' // uppercase/spaces converted to lowercase/hyphens var str1 = 'Original Date: 2017\n' // uppercase/spaces converted to lowercase/hyphens