Refactor l10n code. Remove use of react-intl. (#2975)

Strings from .dtd files are now accessible from Zotero.getMessage
as the eventual move to Fluent would remove their distinction.
This commit is contained in:
Adomas Ven 2023-01-17 22:59:19 +02:00 committed by Adomas Venčkauskas
parent bcfdaaabab
commit cfbfcf20bf
19 changed files with 150 additions and 181 deletions

View file

@ -25,7 +25,6 @@
const React = require('react');
const ReactDOM = require('react-dom');
const { IntlProvider } = require('react-intl');
const LibraryTree = require('./libraryTree');
const VirtualizedTable = require('components/virtualized-table');
const { TreeSelectionStub } = VirtualizedTable;
@ -42,9 +41,7 @@ var CollectionTree = class CollectionTree extends LibraryTree {
var ref;
opts.domEl = domEl;
let elem = (
<IntlProvider locale={Zotero.locale} messages={Zotero.Intl.strings}>
<CollectionTree ref={c => ref = c } {...opts} />
</IntlProvider>
<CollectionTree ref={c => ref = c } {...opts} />
);
await new Promise(resolve => ReactDOM.render(elem, domEl, resolve));

View file

@ -29,7 +29,6 @@ import React, { memo } from 'react';
import ReactDOM from "react-dom";
import PropTypes from 'prop-types';
import cx from 'classnames';
import { IntlProvider, FormattedMessage } from "react-intl";
// This is a quick reimplementation of the annotation for use in the conflict resolution window.
// We'll want to replace this with a single component shared between the PDF reader and the rest
@ -40,31 +39,26 @@ function AnnotationBox({ data }) {
};
return (
<IntlProvider
locale={ Zotero.locale }
messages={ Zotero.Intl.strings }
>
<div className="AnnotationBox">
<div className="title">{Zotero.getString('itemTypes.annotation')}</div>
<div className="container">
<div className="header">
<div>{Zotero.Cite.getLocatorString('page')} {data.pageLabel}</div>
</div>
{data.text !== undefined
? <div className="text" style={textStyle}>{data.text}</div>
: ''}
{data.type == 'image'
// TODO: Localize
// TODO: Render from PDF based on position, if file is the same? Or don't
// worry about it?
? <div className="image-placeholder">[image not shown]</div>
: ''}
{data.comment !== undefined
? <div className="comment">{data.comment}</div>
: ''}
<div className="AnnotationBox">
<div className="title">{Zotero.getString('itemTypes.annotation')}</div>
<div className="container">
<div className="header">
<div>{Zotero.Cite.getLocatorString('page')} {data.pageLabel}</div>
</div>
{data.text !== undefined
? <div className="text" style={textStyle}>{data.text}</div>
: ''}
{data.type == 'image'
// TODO: Localize
// TODO: Render from PDF based on position, if file is the same? Or don't
// worry about it?
? <div className="image-placeholder">[image not shown]</div>
: ''}
{data.comment !== undefined
? <div className="comment">{data.comment}</div>
: ''}
</div>
</IntlProvider>
</div>
);
}

View file

@ -27,7 +27,6 @@
const React = require('react')
const { PureComponent, createElement: create } = React
const { injectIntl } = require('react-intl')
const { IconDownChevron } = require('./icons')
const cx = require('classnames')
const {
@ -59,19 +58,19 @@ class Button extends PureComponent {
}
get text() {
const { intl, text } = this.props
const { text } = this.props;
return text ?
intl.formatMessage({ id: text }) :
null
Zotero.getString(text) :
null;
}
get title() {
const { intl, title } = this.props
const { title } = this.props;
return title ?
intl.formatMessage({ id: title }) :
null
Zotero.getString(title) :
null;
}
get menuMarker() {
@ -159,5 +158,5 @@ class Button extends PureComponent {
module.exports = {
ButtonGroup,
Button: injectIntl(Button)
Button
}

View file

@ -29,7 +29,6 @@ import React, { memo } from 'react';
import ReactDOM from "react-dom";
import PropTypes from 'prop-types';
import cx from 'classnames';
import { IntlProvider } from "react-intl";
function CreateParent({ loading, item, toggleAccept }) {
// When the input has/does not have characters toggle the accept button on the dialog
@ -43,31 +42,26 @@ function CreateParent({ loading, item, toggleAccept }) {
};
return (
<IntlProvider
locale={ Zotero.locale }
messages={ Zotero.Intl.strings }
>
<div className="create-parent-container">
<span className="title">
{ item.attachmentFilename }
</span>
<div className="body">
<input
id="parent-item-identifier"
placeholder={ Zotero.getString('createParent.prompt') }
size="50"
disabled={ loading }
onChange={ handleInput }
/>
<div
mode="undetermined"
className={ cx('downloadProgress', { hidden: !loading }) }
>
<div className="progress-bar"></div>
</div>
<div className="create-parent-container">
<span className="title">
{ item.attachmentFilename }
</span>
<div className="body">
<input
id="parent-item-identifier"
placeholder={ Zotero.getString('createParent.prompt') }
size="50"
disabled={ loading }
onChange={ handleInput }
/>
<div
mode="undetermined"
className={ cx('downloadProgress', { hidden: !loading }) }
>
<div className="progress-bar"></div>
</div>
</div>
</IntlProvider>
</div>
);
}

View file

@ -25,7 +25,6 @@
import React, { memo, useCallback, useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import { getDOMElement } from 'components/icons';
import { IntlProvider } from 'react-intl';
import VirtualizedTable, { renderCell } from 'components/virtualized-table';
import { noop } from './utils';
@ -101,17 +100,15 @@ const ProgressQueueTable = ({ onActivate = noop, progressQueue }) => {
}, []); // eslint-disable-line react-hooks/exhaustive-deps
return (
<IntlProvider locale={ Zotero.locale } messages={ Zotero.Intl.strings }>
<VirtualizedTable
getRowCount={ getRowCount }
ref={ treeRef }
id="progress-queue-table"
renderItem={ rowToTreeItem }
showHeader={ true }
columns={ tableColumns }
onActivate={ onActivate }
/>
</IntlProvider>
<VirtualizedTable
getRowCount={ getRowCount }
ref={ treeRef }
id="progress-queue-table"
renderItem={ rowToTreeItem }
showHeader={ true }
columns={ tableColumns }
onActivate={ onActivate }
/>
);
};

View file

@ -25,7 +25,6 @@
const React = require('react');
const PropTypes = require('prop-types');
const { FormattedMessage } = require('react-intl');
var { Collection } = require('react-virtualized');
// See also .tag-selector-item in _tag-selector.scss
@ -191,14 +190,14 @@ class TagList extends React.PureComponent {
if (!this.props.loaded) {
tagList = (
<div className="tag-selector-message">
<FormattedMessage id="zotero.tagSelector.loadingTags" />
{Zotero.getString('zotero.tagSelector.loadingTags')}
</div>
);
}
else if (tagCount == 0) {
tagList = (
<div className="tag-selector-message">
<FormattedMessage id="zotero.tagSelector.noTagsToDisplay" />
{Zotero.getString('zotero.tagSelector.noTagsToDisplay')}
</div>
);
}

View file

@ -30,7 +30,6 @@ const PropTypes = require('prop-types');
const cx = require('classnames');
const WindowedList = require('./windowed-list');
const Draggable = require('./draggable');
const { injectIntl } = require('react-intl');
const { IconDownChevron, getDOMElement } = require('components/icons');
const TYPING_TIMEOUT = 1000;
@ -1658,7 +1657,7 @@ function makeRowRenderer(getRowData) {
function formatColumnName(column) {
if (column.label in Zotero.Intl.strings) {
return Zotero.Intl.strings[column.label];
return Zotero.getString(column.label);
}
else if (/^[^\s]+\w\.\w[^\s]+$/.test(column.label)) {
try {
@ -1674,7 +1673,7 @@ function formatColumnName(column) {
return column.label;
}
module.exports = injectIntl(VirtualizedTable, { forwardRef: true });
module.exports = VirtualizedTable;
module.exports.TreeSelection = TreeSelection;
module.exports.TreeSelectionStub = TreeSelectionStub;
module.exports.renderCell = renderCell;

View file

@ -31,7 +31,6 @@
const React = require('react');
const ReactDOM = require('react-dom');
const PropTypes = require('prop-types');
const { IntlProvider } = require('react-intl');
const TagSelector = require('components/tagSelector.js');
const defaults = {
tagColors: new Map(),
@ -772,9 +771,7 @@ Zotero.TagSelector = class TagSelectorContainer extends React.PureComponent {
static init(domEl, opts) {
var ref;
let elem = (
<IntlProvider locale={Zotero.locale} messages={Zotero.Intl.strings}>
<TagSelectorContainer ref={c => ref = c } {...opts} />
</IntlProvider>
<TagSelectorContainer ref={c => ref = c } {...opts} />
);
ReactDOM.render(elem, domEl);
ref.domEl = domEl;

View file

@ -931,13 +931,13 @@ var ZoteroContextPane = new function () {
// Info tab
var tabInfo = document.createXULElement('tab');
tabInfo.setAttribute('label', Zotero.Intl.strings['zotero.tabs.info.label']);
tabInfo.setAttribute('label', Zotero.getString('zotero.tabs.info.label'));
// Tags tab
var tabTags = document.createXULElement('tab');
tabTags.setAttribute('label', Zotero.Intl.strings['zotero.tabs.tags.label']);
tabTags.setAttribute('label', Zotero.getString('zotero.tabs.tags.label'));
// Related tab
var tabRelated = document.createXULElement('tab');
tabRelated.setAttribute('label', Zotero.Intl.strings['zotero.tabs.related.label']);
tabRelated.setAttribute('label', Zotero.getString('zotero.tabs.related.label'));
tabs.append(tabInfo, tabTags, tabRelated);
tabbox.append(tabs, tabpanels);

View file

@ -27,7 +27,6 @@ const { noop, getDragTargetOrient } = require("components/utils");
const PropTypes = require("prop-types");
const React = require('react');
const ReactDOM = require('react-dom');
const { IntlProvider } = require('react-intl');
const LibraryTree = require('./libraryTree');
const VirtualizedTable = require('components/virtualized-table');
const { renderCell, formatColumnName } = VirtualizedTable;
@ -48,9 +47,7 @@ var ItemTree = class ItemTree extends LibraryTree {
var ref;
opts.domEl = domEl;
let elem = (
<IntlProvider locale={Zotero.locale} messages={Zotero.Intl.strings}>
<ItemTree ref={c => ref = c } {...opts} />
</IntlProvider>
<ItemTree ref={c => ref = c } {...opts} />
);
await new Promise(resolve => ReactDOM.render(elem, domEl, resolve));
@ -3707,7 +3704,7 @@ var ItemTree = class ItemTree extends LibraryTree {
// Restore Default Column Order
//
let menuitem = doc.createXULElement('menuitem');
menuitem.setAttribute('label', Zotero.Intl.strings['zotero.items.restoreColumnOrder.label']);
menuitem.setAttribute('label', Zotero.getString('zotero.items.restoreColumnOrder.label'));
menuitem.setAttribute('anonid', prefix + 'restore-order');
menuitem.addEventListener('command', () => this.tree._columns.restoreDefaultOrder());
menupopup.appendChild(menuitem);

View file

@ -24,7 +24,6 @@
*/
import VirtualizedTable from 'components/virtualized-table';
const { IntlProvider } = require('react-intl');
import React from 'react';
import ReactDOM from 'react-dom';
@ -41,21 +40,19 @@ function init() {
engines = Zotero.LocateManager.getEngines();
const domEl = document.querySelector('#locateManager-tree');
let elem = (
<IntlProvider locale={Zotero.locale} messages={Zotero.Intl.strings}>
<VirtualizedTable
getRowCount={() => engines.length}
id="locateManager-table"
ref={ref => tree = ref}
renderItem={VirtualizedTable.makeRowRenderer(getRowData)}
showHeader={true}
multiSelect={true}
columns={columns}
onColumnSort={null}
disableFontSizeScaling={true}
getRowString={index => getRowData(index).name}
onActivate={handleActivate}
/>
</IntlProvider>
<VirtualizedTable
getRowCount={() => engines.length}
id="locateManager-table"
ref={ref => tree = ref}
renderItem={VirtualizedTable.makeRowRenderer(getRowData)}
showHeader={true}
multiSelect={true}
columns={columns}
onColumnSort={null}
disableFontSizeScaling={true}
getRowString={index => getRowData(index).name}
onActivate={handleActivate}
/>
);
return new Promise(resolve => ReactDOM.render(elem, domEl, resolve));
}

View file

@ -30,7 +30,6 @@ import FilePicker from 'zotero/modules/filePicker';
var React = require('react');
var ReactDOM = require('react-dom');
var VirtualizedTable = require('components/virtualized-table');
var { IntlProvider } = require('react-intl');
var { makeRowRenderer } = VirtualizedTable;
Zotero_Preferences.Cite = {
@ -102,22 +101,20 @@ Zotero_Preferences.Cite = {
}
};
let elem = (
<IntlProvider locale={Zotero.locale} messages={Zotero.Intl.strings}>
<VirtualizedTable
getRowCount={() => this.styles.length}
id="styleManager-table"
ref={ref => this._tree = ref}
renderItem={makeRowRenderer(index => this.styles[index])}
showHeader={true}
multiSelect={true}
columns={columns}
staticColumns={true}
disableFontSizeScaling={true}
onSelectionChange={selection => document.getElementById('styleManager-delete').disabled = !selection.count}
onKeyDown={handleKeyDown}
getRowString={index => this.styles[index].title}
/>
</IntlProvider>
<VirtualizedTable
getRowCount={() => this.styles.length}
id="styleManager-table"
ref={ref => this._tree = ref}
renderItem={makeRowRenderer(index => this.styles[index])}
showHeader={true}
multiSelect={true}
columns={columns}
staticColumns={true}
disableFontSizeScaling={true}
onSelectionChange={selection => document.getElementById('styleManager-delete').disabled = !selection.count}
onKeyDown={handleKeyDown}
getRowString={index => this.styles[index].title}
/>
);
let styleManager = document.getElementById("styleManager");

View file

@ -28,7 +28,6 @@
var React = require('react');
var ReactDOM = require('react-dom');
var VirtualizedTable = require('components/virtualized-table');
var { IntlProvider } = require('react-intl');
var { makeRowRenderer } = VirtualizedTable;
Zotero_Preferences.Export = {
@ -479,22 +478,20 @@ Zotero_Preferences.Export = {
};
let elem = (
<IntlProvider locale={Zotero.locale} messages={Zotero.Intl.strings}>
<VirtualizedTable
getRowCount={() => this._rows.length}
id="quickCopy-siteSettings-table"
ref={ref => this._tree = ref}
renderItem={makeRowRenderer(index => this._rows[index])}
showHeader={true}
columns={columns}
staticColumns={true}
disableFontSizeScaling={true}
onSelectionChange={handleSelectionChange}
onKeyDown={handleKeyDown}
getRowString={index => this._rows[index].domain}
onActivate={(event, indices) => Zotero_Preferences.Export.showQuickCopySiteEditor(true)}
/>
</IntlProvider>
<VirtualizedTable
getRowCount={() => this._rows.length}
id="quickCopy-siteSettings-table"
ref={ref => this._tree = ref}
renderItem={makeRowRenderer(index => this._rows[index])}
showHeader={true}
columns={columns}
staticColumns={true}
disableFontSizeScaling={true}
onSelectionChange={handleSelectionChange}
onKeyDown={handleKeyDown}
getRowString={index => this._rows[index].domain}
onActivate={(event, indices) => Zotero_Preferences.Export.showQuickCopySiteEditor(true)}
/>
);
await new Promise(resolve => ReactDOM.render(elem, document.getElementById("quickCopy-siteSettings"), resolve));
} else {

View file

@ -32,7 +32,6 @@ var React = require('react');
var ReactDOM = require('react-dom');
var VirtualizedTable = require('components/virtualized-table');
var { getDOMElement } = require('components/icons');
var { IntlProvider } = require('react-intl');
var { renderCell } = VirtualizedTable;
Zotero_Preferences.Sync = {
@ -330,20 +329,18 @@ Zotero_Preferences.Sync = {
}
};
let elem = (
<IntlProvider locale={Zotero.locale} messages={Zotero.Intl.strings}>
<VirtualizedTable
getRowCount={() => this._rows.length}
id="librariesToSync-table"
ref={ref => this._tree = ref}
renderItem={renderItem}
showHeader={true}
columns={columns}
staticColumns={true}
getRowString={index => this._rows[index].name}
disableFontSizeScaling={true}
onKeyDown={handleKeyDown}
/>
</IntlProvider>
<VirtualizedTable
getRowCount={() => this._rows.length}
id="librariesToSync-table"
ref={ref => this._tree = ref}
renderItem={renderItem}
showHeader={true}
columns={columns}
staticColumns={true}
getRowString={index => this._rows[index].name}
disableFontSizeScaling={true}
onKeyDown={handleKeyDown}
/>
);
ReactDOM.render(elem, document.getElementById("libraries-to-sync-tree"));

View file

@ -241,8 +241,8 @@
<html:h1>&zotero.preferences.sync.reset;</html:h1>
<button label="&zotero.preferences.sync.reset.showResetOptions;" oncommand="Zotero_Preferences.navigateToPane('zotero-subpane-reset-sync')"
data-search-strings="
zotero.preferences.sync.reset.restoreToServer,
zotero.preferences.sync.reset.restoreToServer.desc,
zotero.preferences.sync.reset.restoreToOnlineLibrary,
zotero.preferences.sync.reset.restoreToOnlineLibrary.desc,
zotero.preferences.sync.reset.fileSyncHistory,
zotero.preferences.sync.reset.resetFileSyncHistory.desc"/>
</vbox>

View file

@ -31,7 +31,6 @@ import FilePicker from 'zotero/modules/filePicker';
import React from 'react';
import ReactDOM from 'react-dom';
import VirtualizedTable from 'components/virtualized-table';
import { IntlProvider } from 'react-intl';
import { getDOMElement } from 'components/icons';
/**
@ -51,9 +50,9 @@ var Zotero_RTFScan = new function() {
var ids = 0;
var tree;
this._rows = [
{ id: 'unmapped', rtf: Zotero.Intl.strings['zotero.rtfScan.unmappedCitations.label'], collapsed: false },
{ id: 'ambiguous', rtf: Zotero.Intl.strings['zotero.rtfScan.ambiguousCitations.label'], collapsed: false },
{ id: 'mapped', rtf: Zotero.Intl.strings['zotero.rtfScan.mappedCitations.label'], collapsed: false },
{ id: 'unmapped', rtf: Zotero.getString('zotero.rtfScan.unmappedCitations.label'), collapsed: false },
{ id: 'ambiguous', rtf: Zotero.getString('zotero.rtfScan.ambiguousCitations.label'), collapsed: false },
{ id: 'mapped', rtf: Zotero.getString('zotero.rtfScan.mappedCitations.label'), collapsed: false },
];
this._rowMap = {};
this._rows.forEach((row, index) => this._rowMap[row.id] = index);
@ -388,9 +387,9 @@ var Zotero_RTFScan = new function() {
document.documentElement.currentPage = document.getElementById('intro-page');
this._rows = [
{ id: 'unmapped', rtf: Zotero.Intl.strings['zotero.rtfScan.unmappedCitations.label'], collapsed: false },
{ id: 'ambiguous', rtf: Zotero.Intl.strings['zotero.rtfScan.ambiguousCitations.label'], collapsed: false },
{ id: 'mapped', rtf: Zotero.Intl.strings['zotero.rtfScan.mappedCitations.label'], collapsed: false },
{ id: 'unmapped', rtf: Zotero.getString('zotero.rtfScan.unmappedCitations.label'), collapsed: false },
{ id: 'ambiguous', rtf: Zotero.getString('zotero.rtfScan.ambiguousCitations.label'), collapsed: false },
{ id: 'mapped', rtf: Zotero.getString('zotero.rtfScan.mappedCitations.label'), collapsed: false },
];
this._rowMap = {};
this._rows.forEach((row, index) => this._rowMap[row.id] = index);
@ -765,17 +764,15 @@ var Zotero_RTFScan = new function() {
this._initCitationTree = function () {
const domEl = document.querySelector('#tree');
const elem = (
<IntlProvider locale={Zotero.locale} messages={Zotero.Intl.strings}>
<VirtualizedTable
getRowCount={() => this._rows.length}
id="rtfScan-table"
ref={ref => tree = ref}
renderItem={this._renderItem}
showHeader={true}
columns={columns}
disableFontSizeScaling={true}
/>
</IntlProvider>
<VirtualizedTable
getRowCount={() => this._rows.length}
id="rtfScan-table"
ref={ref => tree = ref}
renderItem={this._renderItem}
showHeader={true}
columns={columns}
disableFontSizeScaling={true}
/>
);
return new Promise(resolve => ReactDOM.render(elem, domEl, resolve));
};

View file

@ -55,7 +55,8 @@ Zotero.Intl = new function () {
Components.utils.import("resource://gre/modules/PluralForm.jsm");
bundle = Services.strings.createBundle('chrome://zotero/locale/zotero.properties');
// Exposed for tests
this._bundle = bundle = Services.strings.createBundle('chrome://zotero/locale/zotero.properties');
intlProps = Services.strings.createBundle('chrome://zotero/locale/mozilla/intl.properties');
[pluralFormGet, pluralFormNumForms] = PluralForm.makeGetter(parseInt(getIntlProp('pluralRule', 1)));
@ -129,6 +130,9 @@ Zotero.Intl = new function () {
}
l10n = bundle.formatStringFromName(name, params, params.length);
}
else if (this.strings[name]) {
return this.strings[name];
}
else {
l10n = bundle.GetStringFromName(name);
}

View file

@ -86,10 +86,10 @@
<!ENTITY zotero.preferences.sync.reset.warning3 " for more information.">
<!ENTITY zotero.preferences.sync.reset.resetDataSyncHistory "Reset Data Sync History">
<!ENTITY zotero.preferences.sync.reset.resetDataSyncHistory.desc "Merge local data with remote data, ignoring sync history">
<!ENTITY zotero.preferences.sync.reset.restoreFromServer "Restore from Online Library">
<!ENTITY zotero.preferences.sync.reset.restoreFromServer.desc "Overwrite local Zotero data with data from the online library.">
<!ENTITY zotero.preferences.sync.reset.restoreToServer "Replace Online Library">
<!ENTITY zotero.preferences.sync.reset.restoreToServer.desc "Overwrite online library with local Zotero data">
<!ENTITY zotero.preferences.sync.reset.restoreFromOnlineLibrary "Restore from Online Library">
<!ENTITY zotero.preferences.sync.reset.restoreFromOnlineLibrary.desc "Overwrite local Zotero data with data from the online library.">
<!ENTITY zotero.preferences.sync.reset.restoreToOnlineLibrary "Replace Online Library">
<!ENTITY zotero.preferences.sync.reset.restoreToOnlineLibrary.desc "Overwrite online library with local Zotero data">
<!ENTITY zotero.preferences.sync.reset.resetFileSyncHistory "Reset File Sync History">
<!ENTITY zotero.preferences.sync.reset.resetFileSyncHistory.desc "Compare all attachment files with the storage service">
<!ENTITY zotero.preferences.sync.reset "Reset">

View file

@ -18,9 +18,16 @@ describe("Zotero.Intl", function() {
it("shouldn't ignore whitespace", function () {
assert.equal(Zotero.localeCompare("Chang", "Chan H"), 1);
});
it("shouldn't ignore leading punctuation", function () {
assert.equal(Zotero.localeCompare("_Abcd", "Abcd"), -1);
});
});
it("there should not be duplicate string keys in .dtd and .properties files", function () {
let dtdStrings = Object.keys(Zotero.Intl.strings);
for (let key of dtdStrings) {
assert.throws(() => Zotero.Intl._bundle.GetStringFromName(key));
}
});
});