Change translation keys for components directory

This commit is contained in:
Louis Delbosc 2022-12-06 14:40:02 +01:00
parent 7a2a0a797f
commit 24a656406e
15 changed files with 53 additions and 53 deletions

View File

@ -227,7 +227,7 @@ export class ActionLog extends dispose.Disposable implements IDomComponent {
} }
private _buildLogDom() { private _buildLogDom() {
this._loadActionSummaries().catch((error) => gristNotify(t("ActionLogFailed"))); this._loadActionSummaries().catch((error) => gristNotify(t("Action Log failed to load")));
return dom('div.action_log', return dom('div.action_log',
dom('div.preference_item', dom('div.preference_item',
koForm.checkbox(this._showAllTables, koForm.checkbox(this._showAllTables,
@ -395,7 +395,7 @@ export class ActionLog extends dispose.Disposable implements IDomComponent {
const newName = tableRename[1]; const newName = tableRename[1];
if (!newName) { if (!newName) {
// TODO - find a better way to send informative notifications. // TODO - find a better way to send informative notifications.
gristNotify(t('TableRemovedInAction', {tableId:tableId, actionNum: action.actionNum})); gristNotify(t("Table {{tableId}} was subsequently removed in action #{{actionNum}}", {tableId:tableId, actionNum: action.actionNum}));
return; return;
} }
tableId = newName; tableId = newName;
@ -406,7 +406,7 @@ export class ActionLog extends dispose.Disposable implements IDomComponent {
// Check is this row was removed - if so there's no reason to go on. // Check is this row was removed - if so there's no reason to go on.
if (td.removeRows.indexOf(rowId) >= 0) { if (td.removeRows.indexOf(rowId) >= 0) {
// TODO - find a better way to send informative notifications. // TODO - find a better way to send informative notifications.
gristNotify(t("RowRemovedInAction", {actionNum})); gristNotify(t("This row was subsequently removed in action {{action.actionNum}}", {actionNum}));
return; return;
} }
@ -416,7 +416,7 @@ export class ActionLog extends dispose.Disposable implements IDomComponent {
const newName = columnRename[1]; const newName = columnRename[1];
if (!newName) { if (!newName) {
// TODO - find a better way to send informative notifications. // TODO - find a better way to send informative notifications.
gristNotify(t("ColumnRemovedInAction", {colId, actionNum: action.actionNum})); gristNotify(t("Column {{colId}} was subsequently removed in action #{{action.actionNum}}", {colId, actionNum: action.actionNum}));
return; return;
} }
colId = newName; colId = newName;

View File

@ -655,8 +655,8 @@ export class ChartConfig extends GrainJSDisposable {
testId('error-bars'), testId('error-bars'),
), ),
dom.domComputed(this._optionsObj.prop('errorBars'), (value: ChartOptions["errorBars"]) => dom.domComputed(this._optionsObj.prop('errorBars'), (value: ChartOptions["errorBars"]) =>
value === 'symmetric' ? cssRowHelp(t('EachYFollowedByOne')) : value === 'symmetric' ? cssRowHelp(t("Each Y series is followed by a series for the length of error bars.")) :
value === 'separate' ? cssRowHelp(t('EachYFollowedByTwo')) : value === 'separate' ? cssRowHelp(t("Each Y series is followed by two series, for top and bottom error bars.")) :
null null
), ),
]), ]),
@ -669,7 +669,7 @@ export class ChartConfig extends GrainJSDisposable {
select(this._groupDataColId, this._groupDataOptions), select(this._groupDataColId, this._groupDataOptions),
testId('group-by-column'), testId('group-by-column'),
), ),
cssHintRow(t('CreateSeparateSeries')), cssHintRow(t("Create separate series for each value of the selected column.")),
]), ]),
// TODO: user should select x axis before widget reach page // TODO: user should select x axis before widget reach page
@ -677,7 +677,7 @@ export class ChartConfig extends GrainJSDisposable {
cssRow( cssRow(
select( select(
this._xAxis, this._columnsOptions, this._xAxis, this._columnsOptions,
{ defaultLabel: t('PickColumn') } { defaultLabel: t("Pick a column") }
), ),
testId('x-axis'), testId('x-axis'),
), ),
@ -773,7 +773,7 @@ export class ChartConfig extends GrainJSDisposable {
private async _setGroupDataColumn(colId: string) { private async _setGroupDataColumn(colId: string) {
const viewFields = this._section.viewFields.peek().peek(); const viewFields = this._section.viewFields.peek().peek();
await this._gristDoc.docData.bundleActions(t('SelectedNewGroupDataColumns'), async () => { await this._gristDoc.docData.bundleActions(t("selected new group data columns"), async () => {
this._freezeXAxis.set(true); this._freezeXAxis.set(true);
this._freezeYAxis.set(true); this._freezeYAxis.set(true);
try { try {
@ -872,7 +872,7 @@ export class ChartConfig extends GrainJSDisposable {
private async _setAggregation(val: boolean) { private async _setAggregation(val: boolean) {
try { try {
this._freezeXAxis.set(true); this._freezeXAxis.set(true);
await this._gristDoc.docData.bundleActions(t("ToggleChartAggregation"), async () => { await this._gristDoc.docData.bundleActions(t("Toggle chart aggregation"), async () => {
if (val) { if (val) {
await this._doAggregation(); await this._doAggregation();
} else { } else {

View File

@ -28,8 +28,8 @@ export class CodeEditorPanel extends DisposableWithEvents {
return dom('div.g-code-panel.clipboard', return dom('div.g-code-panel.clipboard',
{tabIndex: "-1"}, {tabIndex: "-1"},
dom.maybe(this._denied, () => dom('div.g-code-panel-denied', dom.maybe(this._denied, () => dom('div.g-code-panel-denied',
dom('h2', dom.text(t('AccessDenied'))), dom('h2', dom.text(t("Access denied"))),
dom('div', dom.text(t('CodeViewOnlyFullAccess'))), dom('div', dom.text(t("Code View is available only when you have full document access."))),
)), )),
dom.maybe(this._schema, (schema) => { dom.maybe(this._schema, (schema) => {
// The reason to scope and rebuild instead of using `kd.text(schema)` is because // The reason to scope and rebuild instead of using `kd.text(schema)` is because

View File

@ -45,7 +45,7 @@ export class DataTables extends Disposable {
cssTableList( cssTableList(
/*************** List section **********/ /*************** List section **********/
testId('list'), testId('list'),
cssHeader(t('RawDataTables')), cssHeader(t("Raw Data Tables")),
cssList( cssList(
dom.forEach(this._tables, tableRec => dom.forEach(this._tables, tableRec =>
cssItem( cssItem(
@ -65,11 +65,11 @@ export class DataTables extends Disposable {
testId('table-id'), testId('table-id'),
dom.text(tableRec.tableId), dom.text(tableRec.tableId),
), ),
{ title : t('ClickToCopy') }, { title : t("Click to copy") },
dom.on('click', async (e, d) => { dom.on('click', async (e, d) => {
e.stopImmediatePropagation(); e.stopImmediatePropagation();
e.preventDefault(); e.preventDefault();
showTransientTooltip(d, t('TableIDCopied'), { showTransientTooltip(d, t("Table ID copied to clipboard"), {
key: 'copy-table-id' key: 'copy-table-id'
}); });
await copyToClipboard(tableRec.tableId.peek()); await copyToClipboard(tableRec.tableId.peek());
@ -127,7 +127,7 @@ export class DataTables extends Disposable {
return [ return [
menuItem( menuItem(
() => this._duplicateTable(table), () => this._duplicateTable(table),
t('DuplicateTable'), t("Duplicate Table"),
testId('menu-duplicate-table'), testId('menu-duplicate-table'),
dom.cls('disabled', use => dom.cls('disabled', use =>
use(isReadonly) || use(isReadonly) ||
@ -144,7 +144,7 @@ export class DataTables extends Disposable {
use(docModel.visibleTables.getObservable()).length <= 1 && !use(table.isHidden) use(docModel.visibleTables.getObservable()).length <= 1 && !use(table.isHidden)
)) ))
), ),
dom.maybe(isReadonly, () => menuText(t("NoEditAccess"))), dom.maybe(isReadonly, () => menuText(t("You do not have edit access to this document"))),
]; ];
} }
@ -160,7 +160,7 @@ export class DataTables extends Disposable {
function doRemove() { function doRemove() {
return docModel.docData.sendAction(['RemoveTable', r.tableId()]); return docModel.docData.sendAction(['RemoveTable', r.tableId()]);
} }
confirmModal(t("DeleteData", {formattedTableName : r.formattedTableName()}), 'Delete', doRemove); confirmModal(t("Delete {{formattedTableName}} data, and remove it from all pages?", {formattedTableName : r.formattedTableName()}), 'Delete', doRemove);
} }
private _tableRows(table: TableRec) { private _tableRows(table: TableRec) {

View File

@ -60,7 +60,7 @@ export class DocumentUsage extends Disposable {
// Invalid row limits are currently treated as if they are undefined. // Invalid row limits are currently treated as if they are undefined.
const maxValue = maxRows && maxRows > 0 ? maxRows : undefined; const maxValue = maxRows && maxRows > 0 ? maxRows : undefined;
return { return {
name: t('Rows'), name: t("Rows"),
currentValue: typeof rowCount !== 'object' ? undefined : rowCount.total, currentValue: typeof rowCount !== 'object' ? undefined : rowCount.total,
maximumValue: maxValue ?? DEFAULT_MAX_ROWS, maximumValue: maxValue ?? DEFAULT_MAX_ROWS,
unit: 'rows', unit: 'rows',
@ -75,7 +75,7 @@ export class DocumentUsage extends Disposable {
// Invalid data size limits are currently treated as if they are undefined. // Invalid data size limits are currently treated as if they are undefined.
const maxValue = maxSize && maxSize > 0 ? maxSize : undefined; const maxValue = maxSize && maxSize > 0 ? maxSize : undefined;
return { return {
name: t('DataSize'), name: t("Data Size"),
currentValue: typeof dataSize !== 'number' ? undefined : dataSize, currentValue: typeof dataSize !== 'number' ? undefined : dataSize,
maximumValue: maxValue ?? DEFAULT_MAX_DATA_SIZE, maximumValue: maxValue ?? DEFAULT_MAX_DATA_SIZE,
unit: 'MB', unit: 'MB',
@ -97,7 +97,7 @@ export class DocumentUsage extends Disposable {
// Invalid attachments size limits are currently treated as if they are undefined. // Invalid attachments size limits are currently treated as if they are undefined.
const maxValue = maxSize && maxSize > 0 ? maxSize : undefined; const maxValue = maxSize && maxSize > 0 ? maxSize : undefined;
return { return {
name: t('AttachmentsSize'), name: t("Attachments Size"),
currentValue: typeof attachmentsSize !== 'number' ? undefined : attachmentsSize, currentValue: typeof attachmentsSize !== 'number' ? undefined : attachmentsSize,
maximumValue: maxValue ?? DEFAULT_MAX_ATTACHMENTS_SIZE, maximumValue: maxValue ?? DEFAULT_MAX_ATTACHMENTS_SIZE,
unit: 'GB', unit: 'GB',
@ -135,7 +135,7 @@ export class DocumentUsage extends Disposable {
public buildDom() { public buildDom() {
return dom('div', return dom('div',
cssHeader(t('Usage'), testId('heading')), cssHeader(t("Usage"), testId('heading')),
dom.domComputed(this._areAllMetricsPending, (isLoading) => { dom.domComputed(this._areAllMetricsPending, (isLoading) => {
if (isLoading) { return cssSpinner(loadingSpinner(), testId('loading')); } if (isLoading) { return cssSpinner(loadingSpinner(), testId('loading')); }
@ -149,7 +149,7 @@ export class DocumentUsage extends Disposable {
return dom.domComputed((use) => { return dom.domComputed((use) => {
const isAccessDenied = use(this._isAccessDenied); const isAccessDenied = use(this._isAccessDenied);
if (isAccessDenied === null) { return null; } if (isAccessDenied === null) { return null; }
if (isAccessDenied) { return buildMessage(t('UsageStatisticsOnlyFullAccess')); } if (isAccessDenied) { return buildMessage(t("Usage statistics are only available to users with full access to the document data.")); }
const org = use(this._currentOrg); const org = use(this._currentOrg);
const product = use(this._currentProduct); const product = use(this._currentProduct);
@ -237,12 +237,12 @@ export function buildUpgradeMessage(
variant: 'short' | 'long', variant: 'short' | 'long',
onUpgrade: () => void, onUpgrade: () => void,
) { ) {
if (!canUpgrade) { return t('LimitContactSiteOwner'); } if (!canUpgrade) { return t("Contact the site owner to upgrade the plan to raise limits."); }
const upgradeLinkText = t('UpgradeLinkText') const upgradeLinkText = t("start your 30-day free trial of the Pro plan.")
// TODO i18next // TODO i18next
return [ return [
variant === 'short' ? null : t('ForHigherLimits'), variant === 'short' ? null : t("For higher limits, "),
buildUpgradeLink( buildUpgradeLink(
variant === 'short' ? capitalizeFirstWord(upgradeLinkText) : upgradeLinkText, variant === 'short' ? capitalizeFirstWord(upgradeLinkText) : upgradeLinkText,
() => onUpgrade(), () => onUpgrade(),

View File

@ -273,7 +273,7 @@ class NotificationAdapter extends Disposable implements Notification {
} }
public showUndoDiscard() { public showUndoDiscard() {
const notifier = this._doc.app.topAppModel.notifier; const notifier = this._doc.app.topAppModel.notifier;
const notification = notifier.createUserMessage(t("UndoDiscard"), { const notification = notifier.createUserMessage(t("Undo discard"), {
message: () => message: () =>
discardNotification( discardNotification(
dom.on("click", () => { dom.on("click", () => {
@ -421,7 +421,7 @@ const styledTooltip = styled('div', `
function cellTooltip(clb: () => any) { function cellTooltip(clb: () => any) {
return function (ctl: ITooltipControl) { return function (ctl: ITooltipControl) {
return styledTooltip( return styledTooltip(
cssLink(t('RestoreLastEdit'), cssLink(t("Restore last edit"),
dom.on('mousedown', (ev) => { ev.preventDefault(); ctl.close(); clb(); }), dom.on('mousedown', (ev) => { ev.preventDefault(); ctl.close(); clb(); }),
testId('draft-tooltip'), testId('draft-tooltip'),
), ),
@ -440,7 +440,7 @@ const styledNotification = styled('div', `
`); `);
function discardNotification(...args: IDomArgs<TagElem<"div">>) { function discardNotification(...args: IDomArgs<TagElem<"div">>) {
return styledNotification( return styledNotification(
t("UndoDiscard"), t("Undo discard"),
testId("draft-notification"), testId("draft-notification"),
...args ...args
); );

View File

@ -314,7 +314,7 @@ export class GristDoc extends DisposableWithEvents {
const importSourceElems = ImportSourceElement.fromArray(this.docPluginManager.pluginsList); const importSourceElems = ImportSourceElement.fromArray(this.docPluginManager.pluginsList);
const importMenuItems = [ const importMenuItems = [
{ {
label: t('ImportFromFile'), label: t("Import from file"),
action: () => Importer.selectAndImport(this, importSourceElems, null, createPreview), action: () => Importer.selectAndImport(this, importSourceElems, null, createPreview),
}, },
...importSourceElems.map(importSourceElem => ({ ...importSourceElems.map(importSourceElem => ({
@ -599,7 +599,7 @@ export class GristDoc extends DisposableWithEvents {
} }
} }
const res = await docData.bundleActions( const res = await docData.bundleActions(
t("AddedNewLinkedSection", {viewName}), t("Added new linked section to view {{viewName}}", {viewName}),
() => this.addWidgetToPageImpl(val, tableId ?? null) () => this.addWidgetToPageImpl(val, tableId ?? null)
); );
@ -680,7 +680,7 @@ export class GristDoc extends DisposableWithEvents {
} }
return await this._viewLayout!.freezeUntil(docData.bundleActions( return await this._viewLayout!.freezeUntil(docData.bundleActions(
t("SavedLinkedSectionIn", {title:section.title(), name: viewModel.name()}), t("Saved linked section {{title}} in view {{name}}", {title:section.title(), name: viewModel.name()}),
async () => { async () => {
// if table changes or a table is made a summary table, let's replace the view section by a // if table changes or a table is made a summary table, let's replace the view section by a

View File

@ -631,7 +631,7 @@ export class Importer extends DisposableWithEvents {
cssMergeOptions( cssMergeOptions(
cssMergeOptionsToggle(labeledSquareCheckbox( cssMergeOptionsToggle(labeledSquareCheckbox(
updateExistingRecords, updateExistingRecords,
t('UpdateExistingRecords'), t("Update existing records"),
dom.autoDispose(updateRecordsListener), dom.autoDispose(updateRecordsListener),
testId('importer-update-existing-records') testId('importer-update-existing-records')
)), )),
@ -646,14 +646,14 @@ export class Importer extends DisposableWithEvents {
return [ return [
cssMergeOptionsMessage( cssMergeOptionsMessage(
t('MergeRowsThatMatch'), t("Merge rows that match these fields:"),
testId('importer-merge-fields-message') testId('importer-merge-fields-message')
), ),
multiSelect( multiSelect(
mergeCols, mergeCols,
section.viewFields().peek().map(f => ({label: f.label(), value: f.colId()})) ?? [], section.viewFields().peek().map(f => ({label: f.label(), value: f.colId()})) ?? [],
{ {
placeholder: t("SelectFieldsToMatch"), placeholder: t("Select fields to match on"),
error: hasInvalidMergeCols error: hasInvalidMergeCols
}, },
dom.autoDispose(mergeColsListener), dom.autoDispose(mergeColsListener),

View File

@ -55,7 +55,7 @@ export class PluginScreen extends Disposable {
public renderError(message: string) { public renderError(message: string) {
this.render([ this.render([
this._buildModalTitle(), this._buildModalTitle(),
cssModalBody(t('ImportFailed'), message, testId('importer-error')), cssModalBody(t("Import failed: "), message, testId('importer-error')),
cssModalButtons( cssModalButtons(
bigBasicButton('Close', bigBasicButton('Close',
dom.on('click', () => this.close()), dom.on('click', () => this.close()),

View File

@ -263,7 +263,7 @@ RecordLayout.prototype.saveLayoutSpec = async function(layoutSpec) {
// Use separate copies of addColAction, since sendTableActions modified each in-place. // Use separate copies of addColAction, since sendTableActions modified each in-place.
let addActions = gutil.arrayRepeat(addColNum, 0).map(() => addColAction.slice()); let addActions = gutil.arrayRepeat(addColNum, 0).map(() => addColAction.slice());
await docData.bundleActions(t('UpdatingRecordLayout'), () => { await docData.bundleActions(t("Updating record layout."), () => {
return Promise.try(() => { return Promise.try(() => {
return addColNum > 0 ? docModel.dataTables[tableId].sendTableActions(addActions) : []; return addColNum > 0 ? docModel.dataTables[tableId].sendTableActions(addActions) : [];
}) })

View File

@ -97,7 +97,7 @@ export class RefSelect extends Disposable {
testId('ref-select-item'), testId('ref-select-item'),
) )
), ),
cssAddLink(cssAddIcon('Plus'), t('AddColumn'), cssAddLink(cssAddIcon('Plus'), t("Add Column"),
menu(() => [ menu(() => [
...this._validCols.peek() ...this._validCols.peek()
.filter((col) => !this._addedSet.peek().has(col.colId.peek())) .filter((col) => !this._addedSet.peek().has(col.colId.peek()))
@ -105,7 +105,7 @@ export class RefSelect extends Disposable {
menuItem(() => this._addFormulaField({ label: col.label(), value: col.colId() }), menuItem(() => this._addFormulaField({ label: col.label(), value: col.colId() }),
col.label.peek()) col.label.peek())
), ),
cssEmptyMenuText(t("NoColumnsAdd")), cssEmptyMenuText(t("No columns to add")),
testId('ref-select-menu'), testId('ref-select-menu'),
]), ]),
testId('ref-select-add'), testId('ref-select-add'),

View File

@ -266,7 +266,7 @@ export class SelectionSummary extends Disposable {
async function doCopy(value: string, elem: Element) { async function doCopy(value: string, elem: Element) {
await copyToClipboard(value); await copyToClipboard(value);
showTransientTooltip(elem, t('CopiedClipboard'), {key: 'copy-selection-summary'}); showTransientTooltip(elem, t("Copied to clipboard"), {key: 'copy-selection-summary'});
} }
const cssSummary = styled('div', ` const cssSummary = styled('div', `

View File

@ -33,7 +33,7 @@ dispose.makeDisposable(ValidationPanel);
ValidationPanel.prototype.onAddRule = function() { ValidationPanel.prototype.onAddRule = function() {
this.validationsTable.sendTableAction(["AddRecord", null, { this.validationsTable.sendTableAction(["AddRecord", null, {
tableRef: this.docTables.at(0).id(), tableRef: this.docTables.at(0).id(),
name: t("RuleLength", {length: this.validations.peekLength + 1}), name: t("Rule {{length}}", {length: this.validations.peekLength + 1}),
formula: "" formula: ""
}]) }])
.then(function() { .then(function() {
@ -86,7 +86,7 @@ ValidationPanel.prototype.buildDom = function() {
2, '', 2, '',
1, kf.buttonGroup( 1, kf.buttonGroup(
kf.button(() => editor.writeObservable(), kf.button(() => editor.writeObservable(),
'Apply', { title: t('UpdateFormula')}, 'Apply', { title: t("Update formula (Shift+Enter)")},
kd.toggleClass('disabled', editorUpToDate) kd.toggleClass('disabled', editorUpToDate)
) )
) )

View File

@ -124,9 +124,9 @@ ViewConfigTab.prototype._buildAdvancedSettingsDom = function() {
const table = sectionData.section.table(); const table = sectionData.section.table();
const isCollapsed = ko.observable(true); const isCollapsed = ko.observable(true);
return [ return [
kf.collapserLabel(isCollapsed, t('AdvancedSettings'), dom.testId('ViewConfig_advanced')), kf.collapserLabel(isCollapsed, t("Advanced settings"), dom.testId('ViewConfig_advanced')),
kf.helpRow(kd.hide(isCollapsed), kf.helpRow(kd.hide(isCollapsed),
t('BigTablesMayBeMarked'), t("Big tables may be marked as \"on-demand\" to avoid loading them into the data engine."),
kd.style('text-align', 'left'), kd.style('text-align', 'left'),
kd.style('margin-top', '1.5rem') kd.style('margin-top', '1.5rem')
), ),
@ -135,7 +135,7 @@ ViewConfigTab.prototype._buildAdvancedSettingsDom = function() {
), ),
kf.row(kd.hide(isCollapsed), kf.row(kd.hide(isCollapsed),
kf.buttonGroup(kf.button(() => this._makeOnDemand(table), kf.buttonGroup(kf.button(() => this._makeOnDemand(table),
kd.text(() => table.onDemand() ? t('UnmarkOnDemandButton') : t('MakeOnDemandButton')), kd.text(() => table.onDemand() ? t("Unmark On-Demand") : t("Make On-Demand")),
dom.testId('ViewConfig_onDemandBtn') dom.testId('ViewConfig_onDemandBtn')
)) ))
), ),
@ -152,9 +152,9 @@ ViewConfigTab.prototype._buildThemeDom = function() {
return cssRow( return cssRow(
dom.autoDispose(theme), dom.autoDispose(theme),
select(theme, [ select(theme, [
{label: t('Form'), value: 'form' }, {label: t("Form"), value: 'form' },
{label: t('Compact'), value: 'compact'}, {label: t("Compact"), value: 'compact'},
{label: t('Blocks'), value: 'blocks' }, {label: t("Blocks"), value: 'blocks' },
]), ]),
testId('detail-theme') testId('detail-theme')
); );
@ -173,7 +173,7 @@ ViewConfigTab.prototype._buildLayoutDom = function() {
const layoutEditorObs = ko.computed(() => view && view.recordLayout && view.recordLayout.layoutEditor()); const layoutEditorObs = ko.computed(() => view && view.recordLayout && view.recordLayout.layoutEditor());
return cssRow({style: 'margin-top: 16px;'}, return cssRow({style: 'margin-top: 16px;'},
kd.maybe(layoutEditorObs, (editor) => editor.buildFinishButtons()), kd.maybe(layoutEditorObs, (editor) => editor.buildFinishButtons()),
primaryButton(t('EditCardLayout'), primaryButton(t("Edit Card Layout"),
dom.autoDispose(layoutEditorObs), dom.autoDispose(layoutEditorObs),
dom.on('click', () => commands.allCommands.editLayout.run()), dom.on('click', () => commands.allCommands.editLayout.run()),
grainjsDom.hide(layoutEditorObs), grainjsDom.hide(layoutEditorObs),
@ -222,8 +222,8 @@ ViewConfigTab.prototype._buildCustomTypeItems = function() {
// 3) // 3)
showObs: () => activeSection().customDef.mode() === "plugin", showObs: () => activeSection().customDef.mode() === "plugin",
buildDom: () => kd.scope(activeSection, ({customDef}) => dom('div', buildDom: () => kd.scope(activeSection, ({customDef}) => dom('div',
kf.row(5, t("PluginColon"), 13, kf.text(customDef.pluginId, {}, {list: "list_plugin"}, dom.testId('ViewConfigTab_customView_pluginId'))), kf.row(5, t("Plugin: "), 13, kf.text(customDef.pluginId, {}, {list: "list_plugin"}, dom.testId('ViewConfigTab_customView_pluginId'))),
kf.row(5, t("SectionColon"), 13, kf.text(customDef.sectionId, {}, {list: "list_section"}, dom.testId('ViewConfigTab_customView_sectionId'))), kf.row(5, t("Section: "), 13, kf.text(customDef.sectionId, {}, {list: "list_section"}, dom.testId('ViewConfigTab_customView_sectionId'))),
// For both `customPlugin` and `selectedSection` it is possible for the value not to be in the // For both `customPlugin` and `selectedSection` it is possible for the value not to be in the
// list of options. Combining <datalist> and <input> allows both to freely edit the value with // list of options. Combining <datalist> and <input> allows both to freely edit the value with
// keyboard and to select it from a list. Although the content of the list seems to be // keyboard and to select it from a list. Although the content of the list seems to be

View File

@ -30,7 +30,7 @@ export async function duplicatePage(gristDoc: GristDoc, pageId: number) {
cssLabel("Name"), cssLabel("Name"),
inputEl = cssInput({value: pageName + ' (copy)'}), inputEl = cssInput({value: pageName + ' (copy)'}),
), ),
t("DoesNotCopyData"), t("Note that this does not copy data, but creates another view of the same data."),
]) ])
)); ));
} }
@ -41,7 +41,7 @@ async function makeDuplicate(gristDoc: GristDoc, pageId: number, pageName: strin
const viewSections = sourceView.viewSections.peek().peek(); const viewSections = sourceView.viewSections.peek().peek();
let viewRef = 0; let viewRef = 0;
await gristDoc.docData.bundleActions( await gristDoc.docData.bundleActions(
t("DuplicatePageName", {pageName}), t("Duplicate page {{pageName}}", {pageName}),
async () => { async () => {
// create new view and new sections // create new view and new sections
const results = await createNewViewSections(gristDoc.docData, viewSections); const results = await createNewViewSections(gristDoc.docData, viewSections);