diff --git a/chrome/content/zotero/components/annotation.jsx b/chrome/content/zotero/components/annotation.jsx index 87b9cd75d5..cbcc61b68f 100644 --- a/chrome/content/zotero/components/annotation.jsx +++ b/chrome/content/zotero/components/annotation.jsx @@ -48,7 +48,7 @@ function AnnotationBox({ data }) {
{Zotero.getString('itemTypes.annotation')}
-
{Zotero.getString('citation.locator.page')} {data.pageLabel}
+
{Zotero.Cite.getLocatorString('page')} {data.pageLabel}
{data.text !== undefined ?
{data.text}
diff --git a/chrome/content/zotero/integration/addCitationDialog.js b/chrome/content/zotero/integration/addCitationDialog.js index d9fe910546..213162030f 100644 --- a/chrome/content/zotero/integration/addCitationDialog.js +++ b/chrome/content/zotero/integration/addCitationDialog.js @@ -113,9 +113,10 @@ var Zotero_Citation_Dialog = new function () { var menu = document.getElementById("label"); var label_list = document.getElementById("locator-type-popup"); var i = 0; + var pageLocatorIndex; for(var value in locators) { 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 var child = document.createXULElement("menuitem"); child.setAttribute("value", value); @@ -124,9 +125,12 @@ var Zotero_Citation_Dialog = new function () { // add to array _locatorIndexArray[locator] = i; _locatorNameArray[i] = locator; + if (locator == 'page') { + pageLocatorIndex = i; + } i++; } - menu.selectedIndex = 0; + menu.selectedIndex = pageLocatorIndex; // load (from selectItemsDialog.js) yield doLoad(); diff --git a/chrome/content/zotero/integration/quickFormat.js b/chrome/content/zotero/integration/quickFormat.js index 8a204ecade..2656bf1b53 100644 --- a/chrome/content/zotero/integration/quickFormat.js +++ b/chrome/content/zotero/integration/quickFormat.js @@ -116,10 +116,9 @@ var Zotero_QuickFormat = new function () { // add labels to popup var locators = Zotero.Cite.labels; - var menu = document.getElementById("locator-label"); var labelList = document.getElementById("locator-label-popup"); 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 var child = document.createXULElement("menuitem"); @@ -127,7 +126,6 @@ var Zotero_QuickFormat = new function () { child.setAttribute("label", locatorLabel); labelList.appendChild(child); } - menu.selectedIndex = 0; } @@ -1090,15 +1088,16 @@ var Zotero_QuickFormat = new function () { let citationItem = JSON.parse(target.dataset.citationItem); panelPrefix.value = citationItem["prefix"] ? citationItem["prefix"] : ""; panelSuffix.value = citationItem["suffix"] ? citationItem["suffix"] : ""; + var pageOption = panelLocatorLabel.getElementsByAttribute("value", "page")[0]; if(citationItem["label"]) { var option = panelLocatorLabel.getElementsByAttribute("value", citationItem["label"]); if(option.length) { panelLocatorLabel.selectedItem = option[0]; } else { - panelLocatorLabel.selectedIndex = 0; + panelLocatorLabel.selectedItem = pageOption; } } else { - panelLocatorLabel.selectedIndex = 0; + panelLocatorLabel.selectedItem = pageOption; } panelLocator.value = citationItem["locator"] ? citationItem["locator"] : ""; panelSuppressAuthor.checked = !!citationItem["suppress-author"]; diff --git a/chrome/content/zotero/tools/csledit.js b/chrome/content/zotero/tools/csledit.js index 6547de9ba1..0fd7568dd7 100644 --- a/chrome/content/zotero/tools/csledit.js +++ b/chrome/content/zotero/tools/csledit.js @@ -56,10 +56,8 @@ var Zotero_CSL_Editor = new function() { var pageList = document.getElementById('zotero-csl-page-type'); var locators = Zotero.Cite.labels; - for (let type of locators) { - var locator = type; - locator = Zotero.getString('citation.locator.'+locator.replace(/\s/g,'')); - pageList.appendItem(locator, type); + for (let locator of locators) { + pageList.appendItem(Zotero.Cite.getLocatorString(locator), locator); } pageList.selectedIndex = 0; diff --git a/chrome/content/zotero/xpcom/cite.js b/chrome/content/zotero/xpcom/cite.js index 51766b096f..b80000ffc2 100644 --- a/chrome/content/zotero/xpcom/cite.js +++ b/chrome/content/zotero/xpcom/cite.js @@ -8,9 +8,105 @@ Zotero.Cite = { /** * Locator labels */ - "labels":["page", "book", "chapter", "column", "figure", "folio", - "issue", "line", "note", "opus", "paragraph", "part", "section", "sub verbo", - "volume", "verse"], + "labels": [ + "act", + "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 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 diff --git a/chrome/locale/en-US/zotero/zotero.properties b/chrome/locale/en-US/zotero/zotero.properties index e886eccb04..b87b1761b0 100644 --- a/chrome/locale/en-US/zotero/zotero.properties +++ b/chrome/locale/en-US/zotero/zotero.properties @@ -861,22 +861,6 @@ citation.showEditor = Show Editor… citation.hideEditor = Hide Editor… citation.citations = Citations 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.parentItem = Parent Item: diff --git a/test/tests/citeTest.js b/test/tests/citeTest.js index 7f90716587..626e887be6 100644 --- a/test/tests/citeTest.js +++ b/test/tests/citeTest.js @@ -1,4 +1,21 @@ 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 () { 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