trad: make the widgets and the Welcome Tour translatable

trad: make the widgets and the Welcome Tour translatable

feat(translation): create automatisation for synchronize key in other locals than en

trad: add french translations

fix(trad): remove all useless code

fix(trad): convert tab to space indentation

fix(trad): add line to english trads
This commit is contained in:
Camille
2023-01-11 18:57:42 +01:00
parent 6804283603
commit 4befca1c92
19 changed files with 248 additions and 112 deletions

View File

@@ -1,3 +1,4 @@
import { makeT } from 'app/client/lib/localization';
import {allCommands} from 'app/client/components/commands';
import {GristDoc} from 'app/client/components/GristDoc';
import {ViewFieldRec} from 'app/client/models/entities/ViewFieldRec';
@@ -7,6 +8,8 @@ import {theme, vars} from 'app/client/ui2018/cssVars';
import {ConditionalStyle} from 'app/client/widgets/ConditionalStyle';
import {Computed, Disposable, dom, DomContents, fromKo, styled} from 'grainjs';
const t = makeT('CellStyle');
export class CellStyle extends Disposable {
constructor(
@@ -20,8 +23,8 @@ export class CellStyle extends Disposable {
public buildDom(): DomContents {
return [
cssLine(
cssLabel('CELL STYLE'),
cssButton('Open row styles', dom.on('click', allCommands.viewTabOpen.run)),
cssLabel(t('CELL STYLE')),
cssButton(t('Open row styles'), dom.on('click', allCommands.viewTabOpen.run)),
),
cssRow(
dom.domComputedOwned(fromKo(this._field.config.style), (holder, options) => {
@@ -58,12 +61,12 @@ export class CellStyle extends Disposable {
}, {
onSave: () => options.save(),
onRevert: () => options.revert(),
placeholder: use => use(hasMixedStyle) ? 'Mixed style' : 'Default cell style'
placeholder: use => use(hasMixedStyle) ? t('Mixed style') : t('Default cell style')
}
);
}),
),
dom.create(ConditionalStyle, "Cell Style", this._field, this._gristDoc, fromKo(this._field.config.multiselect))
dom.create(ConditionalStyle, t("Cell Style"), this._field, this._gristDoc, fromKo(this._field.config.multiselect))
];
}
}

View File

@@ -1,3 +1,4 @@
import {makeT} from 'app/client/lib/localization';
import {DataRowModel} from 'app/client/models/DataRowModel';
import {ViewFieldRec} from 'app/client/models/entities/ViewFieldRec';
import {KoSaveableObservable} from 'app/client/models/modelUtil';
@@ -13,6 +14,8 @@ export type IChoiceOptions = Style
export type ChoiceOptions = Record<string, IChoiceOptions | undefined>;
export type ChoiceOptionsByName = Map<string, IChoiceOptions | undefined>;
const t = makeT('ChoiceTextBox');
export function getRenderFillColor(choiceOptions?: IChoiceOptions) {
return choiceOptions?.fillColor ?? DEFAULT_FILL_COLOR;
}
@@ -78,7 +81,7 @@ export class ChoiceTextBox extends NTextBox {
);
return [
super.buildConfigDom(),
cssLabel('CHOICES'),
cssLabel(t('CHOICES')),
cssRow(
dom.autoDispose(disabled),
dom.autoDispose(mixed),

View File

@@ -1,3 +1,4 @@
import {makeT} from 'app/client/lib/localization';
import {GristDoc} from 'app/client/components/GristDoc';
import {ColumnRec} from 'app/client/models/DocModel';
import {KoSaveableObservable} from 'app/client/models/modelUtil';
@@ -18,6 +19,7 @@ import {Computed, Disposable, dom, DomContents, makeTestId, Observable, styled}
import debounce = require('lodash/debounce');
const testId = makeTestId('test-widget-style-');
const t = makeT('ConditionalStyle');
export class ConditionalStyle extends Disposable {
// Holds data from currently selected record (holds data only when this field has conditional styles).
@@ -71,12 +73,12 @@ export class ConditionalStyle extends Disposable {
{ style: 'margin-top: 16px' },
withInfoTooltip(
textButton(
'Add conditional style',
t('Add conditional style'),
testId('add-conditional-style'),
dom.on('click', () => this._ruleOwner.addEmptyRule()),
dom.prop('disabled', this._disabled),
),
(this._label === 'Row Style'
(this._label === t('Row Style')
? GristTooltips.addRowConditionalStyle()
: GristTooltips.addColumnConditionalStyle()
),
@@ -113,8 +115,8 @@ export class ConditionalStyle extends Disposable {
const errorMessage = Computed.create(owner, use => {
const value = use(currentValue);
return (!use(hasError) ? '' :
isRaisedException(value) ? 'Error in style rule' :
'Rule must return True or False');
isRaisedException(value) ? t('Error in style rule') :
t('Rule must return True or False'));
});
return dom('div',
testId(`conditional-rule-${ruleIndex}`),
@@ -153,7 +155,7 @@ export class ConditionalStyle extends Disposable {
)
),
cssRow(
textButton('Add another rule',
textButton(t('Add another rule'),
dom.on('click', () => this._ruleOwner.addEmptyRule()),
testId('add-another-rule'),
dom.prop('disabled', use => this._disabled && use(this._disabled))

View File

@@ -1,9 +1,12 @@
import { makeT } from 'app/client/lib/localization';
import {ACSelectItem, buildACSelect} from "app/client/lib/ACSelect";
import {Computed, IDisposableOwner, Observable} from "grainjs";
import {ACIndexImpl} from "app/client/lib/ACIndex";
import {testId} from 'app/client/ui2018/cssVars';
import {currencies} from 'app/common/Locales';
const t = makeT('CurrencyPicker');
interface CurrencyPickerOptions {
// The label to use in the select menu for the default option.
defaultCurrencyLabel: string;
@@ -40,7 +43,7 @@ export function buildCurrencyPicker(
save(_, item: ACSelectItem | undefined) {
// Save only if we have found a match
if (!item) {
throw new Error("Invalid currency");
throw new Error(t("Invalid currency"));
}
// For default value, return undefined to use default currency for document.
onSave(item.value === defaultCurrencyLabel ? undefined : item.value);

View File

@@ -1,4 +1,5 @@
import {GristDoc} from 'app/client/components/GristDoc';
import {makeT} from 'app/client/lib/localization';
import {FocusLayer} from 'app/client/lib/FocusLayer';
import {createObsArray} from 'app/client/lib/koArrayWrap';
import {localStorageBoolObs} from 'app/client/lib/localStorageObs';
@@ -35,6 +36,7 @@ import maxSize from 'popper-max-size-modifier';
import flatMap = require('lodash/flatMap');
const testId = makeTestId('test-discussion-');
const t = makeT('DiscussionEditor');
const COMMENTS_LIMIT = 200;
interface DiscussionPopupProps {
@@ -68,7 +70,7 @@ export class CellWithComments extends Disposable implements ICellView {
public async reply(comment: CellRec, text: string): Promise<void> {
const author = commentAuthor(this.gristDoc);
await this.gristDoc.docData.bundleActions("Reply to a comment", () => Promise.all([
await this.gristDoc.docData.bundleActions(t("Reply to a comment"), () => Promise.all([
this.gristDoc.docModel.cells.sendTableAction([
"AddRecord",
null,
@@ -150,7 +152,7 @@ export class EmptyCell extends CellWithComments implements ICellView {
})
}
];
await props.gristDoc.docData.sendActions([addComment], 'Started discussion');
await props.gristDoc.docData.sendActions([addComment], t('Started discussion'));
}
}
@@ -221,9 +223,9 @@ class EmptyCellView extends Disposable {
text: this._newText,
onSave: () => this.props.onSave(this._newText.get()),
onCancel: () => this.props.closeClicked?.(),
editorArgs: [{placeholder: 'Write a comment'}],
mainButton: 'Comment',
buttons: ['Cancel'],
editorArgs: [{placeholder: t('Write a comment')}],
mainButton: t('Comment'),
buttons: [t('Cancel')],
args: [testId('editor-start')]
}));
}
@@ -274,7 +276,7 @@ class CellWithCommentsView extends Disposable implements IDomComponent {
public buildDom() {
return cssTopic(
dom.maybe(this._truncated, () => cssTruncate(`Showing last ${COMMENTS_LIMIT} comments`)),
dom.maybe(this._truncated, () => cssTruncate(t("Showing last {{nb}} comments", {nb: COMMENTS_LIMIT}))),
cssTopic.cls('-panel', this.props.panel),
domOnCustom(CommentView.EDIT, (s: CommentView) => this._onEditComment(s)),
domOnCustom(CommentView.CANCEL, (s: CommentView) => this._onCancelEdit()),
@@ -358,7 +360,7 @@ class CellWithCommentsView extends Disposable implements IDomComponent {
onSave: () => this._save(),
onCancel: () => this.props.closeClicked?.(),
mainButton: 'Send',
editorArgs: [{placeholder: 'Comment'}],
editorArgs: [{placeholder: t('Comment')}],
args: [testId('editor-add')]
}));
}
@@ -464,8 +466,8 @@ class CommentView extends Disposable {
const text = Observable.create(owner, comment.text.peek() ?? '');
return dom.create(CommentEntry, {
text,
mainButton: 'Save',
buttons: ['Cancel'],
mainButton: t('Save'),
buttons: [t('Cancel')],
onSave: async () => {
const value = text.get();
text.set("");
@@ -503,7 +505,7 @@ class CommentView extends Disposable {
dom.maybe(use => !use(this.isEditing) && !this.props.isReply && !use(comment.resolved),
() => dom.domComputed(use => {
if (!use(this.replying)) {
return cssReplyButton(icon('Message'), 'Reply',
return cssReplyButton(icon('Message'), t('Reply'),
testId('comment-reply-button'),
dom.on('click', withStop(() => this.replying.set(true))),
dom.style('margin-left', use2 => use2(this._hasReplies) ? '16px' : '0px'),
@@ -513,8 +515,8 @@ class CommentView extends Disposable {
return dom.create(CommentEntry, {
text,
args: [dom.style('margin-top', '8px'), testId('editor-reply')],
mainButton: 'Reply',
buttons: ['Cancel'],
mainButton: t('Reply'),
buttons: [t('Cancel')],
onSave: async () => {
const value = text.get();
this.replying.set(false);
@@ -522,7 +524,7 @@ class CommentView extends Disposable {
},
onCancel: () => this.replying.set(false),
onClick: (button) => {
if (button === 'Cancel') {
if (button === t('Cancel')) {
this.replying.set(false);
}
},
@@ -538,7 +540,7 @@ class CommentView extends Disposable {
testId('comment-resolved'),
icon('FieldChoice'),
cssResolvedText(dom.text(
`Marked as resolved`
t(`Marked as resolved`)
)));
}),
]),
@@ -554,23 +556,23 @@ class CommentView extends Disposable {
!canResolve ? null :
menuItem(
() => this.props.topic.resolve(this.props.comment),
'Resolve'
t('Resolve')
),
!comment.resolved() ? null :
menuItem(
() => this.props.topic.open(comment),
'Open'
t('Open')
),
menuItem(
() => this.props.topic.remove(comment),
'Remove',
t('Remove'),
dom.cls('disabled', use => {
return currentUser !== use(comment.userRef);
})
),
menuItem(
() => this._edit(),
'Edit',
t('Edit'),
dom.cls('disabled', use => {
return currentUser !== use(comment.userRef);
})
@@ -605,7 +607,7 @@ class CommentEntry extends Disposable {
public buildDom() {
const text = this.props.text;
const clickBuilder = (button: string) => dom.on('click', () => {
if (button === "Cancel") {
if (button === t("Cancel")) {
this.props.onCancel?.();
} else {
this.props.onClick?.(button);
@@ -699,9 +701,9 @@ export class DiscussionPanel extends Disposable implements IDomComponent {
const tables = Computed.create(owner, use => {
// Filter out those tables that are not available by ACL.
if (use(this._currentPageKo)) {
return [...new Set(use(viewSections).map(vs => use(vs.table)).filter(t => use(t.tableId)))];
return [...new Set(use(viewSections).map(vs => use(vs.table)).filter(tb => use(tb.tableId)))];
} else {
return use(this._grist.docModel.visibleTables.getObservable()).filter(t => use(t.tableId));
return use(this._grist.docModel.visibleTables.getObservable()).filter(tb => use(tb.tableId));
}
});
@@ -774,8 +776,8 @@ export class DiscussionPanel extends Disposable implements IDomComponent {
;
});
const allDiscussions = Computed.create(owner, use => {
const list = flatMap(flatMap(use(tables).map(t => {
const columns = use(use(t.columns).getObservable());
const list = flatMap(flatMap(use(tables).map(tb => {
const columns = use(use(tb.columns).getObservable());
const dList = columns.map(col => use(use(col.cells).getObservable())
.filter(c => use(c.root) && use(c.type) === CellInfoType.COMMENT));
return dList;
@@ -818,9 +820,9 @@ export class DiscussionPanel extends Disposable implements IDomComponent {
testId('panel-menu'),
menu(() => {
return [cssDropdownMenu(
labeledSquareCheckbox(this._onlyMine, "Only my threads", testId('my-threads')),
labeledSquareCheckbox(this._currentPage, "Only current page", testId('only-page')),
labeledSquareCheckbox(this._resolved, "Show resolved comments", testId('show-resolved')),
labeledSquareCheckbox(this._onlyMine, t("Only my threads"), testId('my-threads')),
labeledSquareCheckbox(this._currentPage, t("Only current page"), testId('only-page')),
labeledSquareCheckbox(this._resolved, t("Show resolved comments"), testId('show-resolved')),
)];
}, {placement: 'bottom-start'}),
dom.on('click', stopPropagation)

View File

@@ -1,13 +1,16 @@
import {makeT} from 'app/client/lib/localization';
import {ITooltipControl, showTooltip, tooltipCloseButton} from 'app/client/ui/tooltips';
import {colors, testId} from 'app/client/ui2018/cssVars';
import {icon} from 'app/client/ui2018/icons';
import {cssLink} from 'app/client/ui2018/links';
import {dom, styled} from 'grainjs';
const t = makeT('DiscussionEditor');
export function showTooltipToCreateFormula(editorDom: HTMLElement, convert: () => void) {
function buildTooltip(ctl: ITooltipControl) {
return cssConvertTooltip(icon('Convert'),
cssLink('Convert column to formula',
cssLink(t('Convert column to formula'),
dom.on('mousedown', (ev) => { ev.preventDefault(); convert(); }),
testId('editor-tooltip-convert'),
),

View File

@@ -9,6 +9,7 @@ import { KoArray } from 'app/client/lib/koArray';
import * as kd from 'app/client/lib/koDom';
import * as kf from 'app/client/lib/koForm';
import * as koUtil from 'app/client/lib/koUtil';
import { makeT } from 'app/client/lib/localization';
import { reportError } from 'app/client/models/AppModel';
import { DataRowModel } from 'app/client/models/DataRowModel';
import { ColumnRec, DocModel, ViewFieldRec } from 'app/client/models/DocModel';
@@ -38,7 +39,7 @@ import * as ko from 'knockout';
import * as _ from 'underscore';
const testId = makeTestId('test-fbuilder-');
const t = makeT('FieldBuilder');
// Creates a FieldBuilder object for each field in viewFields
@@ -228,7 +229,7 @@ export class FieldBuilder extends Disposable {
defaultWidget.onWrite((value) => this.field.config.widget(value));
const disabled = Computed.create(null, use => !use(this.field.config.sameWidgets));
return [
cssLabel('CELL FORMAT'),
cssLabel(t('CELL FORMAT')),
cssRow(
grainjsDom.autoDispose(defaultWidget),
widgetOptions.length <= 2 ?
@@ -242,7 +243,7 @@ export class FieldBuilder extends Disposable {
widgetOptions,
{
disabled,
defaultLabel: 'Mixed format'
defaultLabel: t('Mixed format')
}
),
testId('widget-select')
@@ -286,7 +287,7 @@ export class FieldBuilder extends Disposable {
// If we are waiting for a server response
use(this.isCallPending),
menuCssClass: cssTypeSelectMenu.className,
defaultLabel: 'Mixed types',
defaultLabel: t('Mixed types'),
renderOptionArgs: (op) => {
if (['Ref', 'RefList'].includes(selectType.get())) {
// Don't show tip if a reference column type is already selected.
@@ -340,7 +341,7 @@ export class FieldBuilder extends Disposable {
// If we selected multiple empty/formula columns, make the change for all of them.
if (this.field.viewSection.peek().selectedFields.peek().length > 1 &&
['formula', 'empty'].indexOf(this.field.viewSection.peek().columnsBehavior.peek())) {
return this.gristDoc.docData.bundleActions("Changing multiple column types", () =>
return this.gristDoc.docData.bundleActions(t("Changing multiple column types"), () =>
Promise.all(this.field.viewSection.peek().selectedFields.peek().map(f =>
f.column.peek().type.setAndSave(calculatedType)
))).catch(reportError);
@@ -369,7 +370,7 @@ export class FieldBuilder extends Disposable {
return use(this.origColumn.disableModifyBase) || use(this.field.config.multiselect);
});
return [
cssLabel('DATA FROM TABLE',
cssLabel(t('DATA FROM TABLE'),
!this._showRefConfigPopup.peek() ? null : this.gristDoc.behavioralPromptsManager.attachTip(
'referenceColumnsConfig',
{
@@ -417,7 +418,7 @@ export class FieldBuilder extends Disposable {
}
}),
kf.row(
15, kf.label('Apply Formula to Data'),
15, kf.label(t('Apply Formula to Data')),
3, kf.buttonGroup(
kf.checkButton(transformButton,
dom('span.glyphicon.glyphicon-flash'),
@@ -498,7 +499,7 @@ export class FieldBuilder extends Disposable {
public fieldSettingsUseSeparate() {
return this.gristDoc.docData.bundleActions(
`Use separate field settings for ${this.origColumn.colId()}`, () => {
t("Use separate field settings for {{colId}}", { colId: this.origColumn.colId() }), () => {
return Promise.all([
setSaveValue(this.field.widgetOptions, this.field.column().widgetOptions()),
setSaveValue(this.field.visibleCol, this.field.column().visibleCol()),
@@ -510,7 +511,7 @@ export class FieldBuilder extends Disposable {
public fieldSettingsSaveAsCommon() {
return this.gristDoc.docData.bundleActions(
`Save field settings for ${this.origColumn.colId()} as common`, () => {
t("Save field settings for {{colId}} as common", { colId: this.origColumn.colId() }), () => {
return Promise.all([
setSaveValue(this.field.column().widgetOptions, this.field.widgetOptions()),
setSaveValue(this.field.column().visibleCol, this.field.visibleCol()),
@@ -525,7 +526,7 @@ export class FieldBuilder extends Disposable {
public fieldSettingsRevertToCommon() {
return this.gristDoc.docData.bundleActions(
`Revert field settings for ${this.origColumn.colId()} to common`, () => {
t("Revert field settings for {{colId}} to common", { colId: this.origColumn.colId() }), () => {
return Promise.all([
setSaveValue(this.field.widgetOptions, ''),
setSaveValue(this.field.visibleCol, 0),

View File

@@ -2,6 +2,7 @@ import * as commands from 'app/client/components/commands';
import {Cursor} from 'app/client/components/Cursor';
import {GristDoc} from 'app/client/components/GristDoc';
import {UnsavedChange} from 'app/client/components/UnsavedChanges';
import {makeT} from 'app/client/lib/localization';
import {DataRowModel} from 'app/client/models/DataRowModel';
import {ViewFieldRec} from 'app/client/models/entities/ViewFieldRec';
import {reportError} from 'app/client/models/errors';
@@ -17,6 +18,8 @@ import {CellPosition} from "app/client/components/CellPosition";
type IEditorConstructor = typeof NewBaseEditor;
const t = makeT('FieldEditor');
/**
* Check if the typed-in value should change the cell without opening the cell editor, and if so,
* saves and returns true. E.g. on typing space, CheckBoxEditor toggles the cell without opening.
@@ -320,7 +323,7 @@ export class FieldEditor extends Disposable {
await editor.prepForSave();
if (this.isDisposed()) {
// We shouldn't normally get disposed here, but if we do, avoid confusing JS errors.
console.warn("Unable to finish saving edited cell"); // tslint:disable-line:no-console
console.warn(t("Unable to finish saving edited cell")); // tslint:disable-line:no-console
return false;
}
@@ -349,7 +352,7 @@ export class FieldEditor extends Disposable {
const value = editor.getCellValue();
if (col.isRealFormula()) {
// tslint:disable-next-line:no-console
console.warn("It should be impossible to save a plain data value into a formula column");
console.warn(t("It should be impossible to save a plain data value into a formula column"));
} else {
// This could still be an isFormula column if it's empty (isEmpty is true), but we don't
// need to toggle isFormula in that case, since the data engine takes care of that.

View File

@@ -1,5 +1,6 @@
import * as AceEditor from 'app/client/components/AceEditor';
import {createGroup} from 'app/client/components/commands';
import {makeT} from 'app/client/lib/localization';
import {DataRowModel} from 'app/client/models/DataRowModel';
import {ViewFieldRec} from 'app/client/models/entities/ViewFieldRec';
import {colors, testId, theme} from 'app/client/ui2018/cssVars';
@@ -20,6 +21,7 @@ import debounce = require('lodash/debounce');
// How wide to expand the FormulaEditor when an error is shown in it.
const minFormulaErrorWidth = 400;
const t = makeT('FormulaEditor');
export interface IFormulaEditorOptions extends Options {
cssClass?: string;
@@ -293,7 +295,7 @@ export function openFormulaEditor(options: {
const column = options.column ?? options.field?.column();
if (!column) {
throw new Error('Column or field is required');
throw new Error(t('Column or field is required'));
}
// AsyncOnce ensures it's called once even if triggered multiple times.
@@ -338,7 +340,7 @@ export function openFormulaEditor(options: {
const editingFormula = options.editingFormula ?? options?.field?.editingFormula;
if (!editingFormula) {
throw new Error('editingFormula is required');
throw new Error(t('editingFormula is required'));
}
// When formula is empty enter formula-editing mode (highlight formula icons; click on a column inserts its ID).
@@ -393,9 +395,9 @@ export function createFormulaErrorObs(owner: MultiHolder, gristDoc: GristDoc, or
const numErrors = tableData.countErrors(colId) || 0;
errorMessage.set(
(numErrors === 0) ? '' :
(numCells === 1) ? `Error in the cell` :
(numErrors === numCells) ? `Errors in all ${numErrors} cells` :
`Errors in ${numErrors} of ${numCells} cells`
(numCells === 1) ? t(`Error in the cell`) :
(numErrors === numCells) ? t(`Errors in all {{numErrors}} cells`, {numErrors}) :
t(`Errors in {{numErrors}} of {{numCells}} cells`, {numErrors, numCells})
);
} else {
errorMessage.set('');

View File

@@ -1,6 +1,9 @@
import {makeT} from 'app/client/lib/localization';
import {FieldOptions} from 'app/client/widgets/NewBaseEditor';
import {NTextEditor} from 'app/client/widgets/NTextEditor';
const t = makeT('HyperLinkEditor');
/**
* HyperLinkEditor - Is the same NTextEditor but with some placeholder text to help explain
* to the user how links should be formatted.
@@ -8,6 +11,6 @@ import {NTextEditor} from 'app/client/widgets/NTextEditor';
export class HyperLinkEditor extends NTextEditor {
constructor(options: FieldOptions) {
super(options);
this.textInput.setAttribute('placeholder', '[link label] url');
this.textInput.setAttribute('placeholder', t('[link label] url'));
}
}

View File

@@ -1,6 +1,7 @@
/**
* See app/common/NumberFormat for description of options we support.
*/
import {makeT} from 'app/client/lib/localization';
import {ViewFieldRec} from 'app/client/models/entities/ViewFieldRec';
import {reportError} from 'app/client/models/errors';
import {cssLabel, cssRow} from 'app/client/ui/RightPanelStyles';
@@ -16,6 +17,7 @@ import {BindableValue, Computed, dom, DomContents, DomElementArg,
import * as LocaleCurrency from 'locale-currency';
const t = makeT('NumericTextBox');
const modeOptions: Array<ISelectorOption<NumMode>> = [
{value: 'currency', label: '$'},
{value: 'decimal', label: ','},
@@ -85,23 +87,23 @@ export class NumericTextBox extends NTextBox {
return [
super.buildConfigDom(),
cssLabel('Number Format'),
cssLabel(t('Number Format')),
cssRow(
dom.autoDispose(holder),
makeButtonSelect(numMode, modeOptions, setMode, disabledStyle, cssModeSelect.cls(''), testId('numeric-mode')),
makeButtonSelect(numSign, signOptions, setSign, disabledStyle, cssSignSelect.cls(''), testId('numeric-sign')),
),
dom.maybe((use) => use(numMode) === 'currency', () => [
cssLabel('Currency'),
cssLabel(t('Currency')),
cssRow(
dom.domComputed(docCurrency, (defaultCurrency) =>
buildCurrencyPicker(holder, currency, setCurrency,
{defaultCurrencyLabel: `Default currency (${defaultCurrency})`, disabled})
{defaultCurrencyLabel: t(`Default currency ({{defaultCurrency}})`, {defaultCurrency}), disabled})
),
testId("numeric-currency")
)
]),
cssLabel('Decimals'),
cssLabel(t('Decimals')),
cssRow(
decimals('min', minDecimals, defaultMin, setMinDecimals, disabled, testId('numeric-min-decimals')),
decimals('max', maxDecimals, defaultMax, setMaxDecimals, disabled, testId('numeric-max-decimals')),

View File

@@ -1,3 +1,4 @@
import {makeT} from 'app/client/lib/localization';
import {DataRowModel} from 'app/client/models/DataRowModel';
import {ViewFieldRec} from 'app/client/models/entities/ViewFieldRec';
import {cssLabel, cssRow} from 'app/client/ui/RightPanelStyles';
@@ -8,6 +9,9 @@ import {NTextBox} from 'app/client/widgets/NTextBox';
import {isFullReferencingType, isVersions} from 'app/common/gristTypes';
import {Computed, dom, styled} from 'grainjs';
const t = makeT('Reference');
/**
* Reference - The widget for displaying references to another table's records.
*/
@@ -33,14 +37,14 @@ export class Reference extends NTextBox {
icon: 'FieldColumn',
disabled: isFullReferencingType(use(col.type)) || use(col.isTransforming)
}))
.concat([{label: 'Row ID', value: 0, icon: 'FieldColumn'}]);
.concat([{label: t('Row ID'), value: 0, icon: 'FieldColumn'}]);
});
}
public buildConfigDom() {
return [
this.buildTransformConfigDom(),
cssLabel('CELL FORMAT'),
cssLabel(t('CELL FORMAT')),
super.buildConfigDom()
];
}
@@ -48,7 +52,7 @@ export class Reference extends NTextBox {
public buildTransformConfigDom() {
const disabled = Computed.create(null, use => use(this.field.config.multiselect));
return [
cssLabel('SHOW COLUMN'),
cssLabel(t('SHOW COLUMN')),
cssRow(
dom.autoDispose(disabled),
select(this._visibleColRef, this._validCols, {

View File

@@ -36,6 +36,7 @@ export function mergeOptions(options: any, type: string) {
// The names of widgets are used, instead of the actual classes needed, in order to limit
// the spread of dependencies. See ./UserTypeImpl for actual classes.
export const typeDefs: any = {
// TODO : translate labels (can not use classic makeT function)
Any: {
label: 'Any',
icon: 'FieldAny',