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('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