(core) updates from grist-core

This commit is contained in:
Paul Fitzpatrick 2023-01-30 09:09:11 -05:00
commit 671e479bad
22 changed files with 691 additions and 118 deletions

61
.github/workflows/translation_keys.yml vendored Normal file
View File

@ -0,0 +1,61 @@
name: Translation keys
on:
push:
branches: [ main ]
workflow_dispatch:
permissions:
pull-requests: write
contents: write
jobs:
build:
if: github.repository_owner == 'gristlabs'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0 # Let's get all the branches
- name: Use Node.js
uses: actions/setup-node@v1
with:
node-version: 14
- name: Install Node.js packages
run: yarn install
- name: Build code
run: yarn run build:prod
- name: Scan for keys
id: scan-keys
run: |
git checkout -b translation-keys
yarn run generate:translation
git status --porcelain
if [[ $(git status --porcelain | wc -l) -eq "0" ]]; then
echo "No changes"
echo "CHANGED=false" >> $GITHUB_ENV
else
echo "Changes detected"
echo "CHANGED=true" >> $GITHUB_ENV
fi
- name: setup git config
run: |
git config user.name "Paul's Grist Bot"
git config user.email "<paul+bot@getgrist.com>"
- name: Prepare PR
if: env.CHANGED == 'true'
run: |
git commit -m "automated update to translation keys" -a
git push --set-upstream origin HEAD:translation-keys -f
num=$(gh pr list --search "automated update to translation keys" --json number -q ".[].number")
if [[ "$num" = "" ]]; then
gh pr create --fill
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -22,6 +22,8 @@ export const cssHelp = styled('div', `
export const cssRow = styled('div', `
display: flex;
flex-wrap: wrap;
row-gap: 5px;
margin: 8px 16px;
align-items: center;
color: ${theme.text};

View File

@ -1,3 +1,4 @@
import { makeT } from 'app/client/lib/localization';
import * as commands from 'app/client/components/commands';
import { urlState } from 'app/client/models/gristUrlState';
import { IOnBoardingMsg, startOnBoarding } from "app/client/ui/OnBoardingPopups";
@ -6,25 +7,26 @@ import { icon } from "app/client/ui2018/icons";
import { cssLink } from "app/client/ui2018/links";
import { dom, styled } from "grainjs";
const t = makeT('WelcomeTour');
export const welcomeTour: IOnBoardingMsg[] = [
{
title: 'Editing Data',
title: t('Editing Data'),
body: () => [
dom('p',
'Double-click or hit ', Key(KeyContent('Enter')), ' on a cell to edit it. ',
'Start with ', Key(KeyStrong('=')), ' to enter a formula.'
)
t('Double-click or hit {{enter}} on a cell to edit it. ', {enter: Key(KeyContent(t('Enter')))}),
t('Start with {{equal}} to enter a formula.', { equal: Key(KeyStrong('=')) }))
],
selector: '.field_clip',
placement: 'bottom',
},
{
selector: '.tour-creator-panel',
title: 'Configuring your document',
title: t('Configuring your document'),
body: () => [
dom('p',
'Toggle the ', dom('em', 'creator panel'), ' to format columns, ',
'convert to card view, select data, and more.'
t('Toggle the {{creatorPanel}} to format columns, ', {creatorPanel: dom('em', t('creator panel'))}),
t('convert to card view, select data, and more.')
)
],
placement: 'left',
@ -32,50 +34,53 @@ export const welcomeTour: IOnBoardingMsg[] = [
},
{
selector: '.tour-type-selector',
title: 'Customizing columns',
title: t('Customizing columns'),
body: () => [
dom('p',
'Set formatting options, formulas, or column types, such as dates, choices, or attachments. '),
t('Set formatting options, formulas, or column types, such as dates, choices, or attachments. ')),
dom('p',
'Make it relational! Use the ', Key('Reference'), ' type to link tables. '
t('Make it relational! Use the {{ref}} type to link tables. ', {ref: Key(t('Reference'))}),
)
],
placement: 'right',
},
{
selector: '.tour-add-new',
title: 'Building up',
title: t('Building up'),
body: () => [
dom('p', 'Use ', Key('Add New'), ' to add widgets, pages, or import more data. ')
dom('p', t('Use {{addNew}} to add widgets, pages, or import more data. ', {addNew: Key(t('Add New'))}))
],
placement: 'right',
},
{
selector: '.tour-share-icon',
title: 'Sharing',
title: t('Sharing'),
body: () => [
dom('p', 'Use the Share button (', TopBarButtonIcon('Share'), ') to share the document or export data.')
dom('p', t('Use the Share button ({{share}}) to share the document or export data.',
{share: TopBarButtonIcon(t('Share'))}))
],
placement: 'bottom',
cropPadding: true,
},
{
selector: '.tour-help-center',
title: 'Flying higher',
title: t('Flying higher'),
body: () => [
dom('p', 'Use ', Key(GreyIcon('Help'), 'Help Center'), ' for documentation or questions.'),
dom('p', t('Use {{helpCenter}} for documentation or questions.',
{helpCenter: Key(GreyIcon('Help'), t('Help Center'))})),
],
placement: 'right',
},
{
selector: '.tour-welcome',
title: 'Welcome to Grist!',
title: t('Welcome to Grist!'),
body: () => [
dom('p', 'Browse our ',
cssLink({target: '_blank', href: urlState().makeUrl({homePage: "templates"})},
'template library', cssInlineIcon('FieldLink')),
"to discover what's possible and get inspired."
),
dom('p', t("Browse our {{templateLibrary}} to discover what's possible and get inspired.",
{
templateLibrary: cssLink({ target: '_blank', href: urlState().makeUrl({ homePage: "templates" }) },
t('template library'), cssInlineIcon('FieldLink'))
}
)),
],
showHasModal: true,
}

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

@ -6,20 +6,20 @@
height: 16px;
}
.field_clip.has_cursor > .widget_checkbox {
:not(.formula_field)>.field_clip.has_cursor>.widget_checkbox {
cursor: pointer;
box-shadow: inset 0 0 0 1px #606060;
border-radius: 3px;
background: linear-gradient(to bottom, rgba(255,255,255,1) 0%, rgba(252,252,252,1) 29%, rgba(239,239,239,1) 50%, rgba(232,232,232,1) 50%, rgba(242,242,242,1) 100%);
}
.widget_checkbox:hover:not(.disabled) {
:not(.formula_field)>.field_clip>.widget_checkbox:hover:not(.disabled) {
cursor: pointer;
box-shadow: inset 0 0 0 1px #606060;
border-radius: 3px;
background: linear-gradient(to bottom, rgba(255,255,255,1) 0%, rgba(252,252,252,1) 29%, rgba(239,239,239,1) 50%, rgba(232,232,232,1) 50%, rgba(242,242,242,1) 100%);
}
.widget_checkbox:active:not(.disabled) {
:not(.formula_field)>.field_clip>.widget_checkbox:active:not(.disabled) {
background: linear-gradient(to bottom, rgba(147,180,242,1) 0%, rgba(135,168,233,1) 10%, rgba(115,149,218,1) 25%, rgba(115,150,224,1) 37%, rgba(115,153,230,1) 50%, rgba(86,134,219,1) 51%, rgba(130,174,235,1) 83%, rgba(151,194,243,1) 100%);
}

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('EditorTooltip');
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',

View File

@ -39,7 +39,8 @@
"Users": "Benutzer",
"View As": "Anzeigen als",
"Seed rules": "Saatgut-Regeln",
"When adding table rules, automatically add a rule to grant OWNER full access.": "Beim Hinzufügen von Tabellenregeln wird automatisch eine Regel hinzugefügt, um BESITZER vollen Zugriff zu gewähren."
"When adding table rules, automatically add a rule to grant OWNER full access.": "Beim Hinzufügen von Tabellenregeln wird automatisch eine Regel hinzugefügt, um BESITZER vollen Zugriff zu gewähren.",
"Permission to edit document structure": "Berechtigung zur Bearbeitung der Dokumentenstruktur"
},
"AccountPage": {
"API": "API",
@ -274,7 +275,10 @@
"Save": "Speichern",
"Save and Reload": "Speichern und neu laden",
"This document's ID (for API use):": "Die ID dieses Dokuments (für API-Verwendung):",
"Time Zone:": "Zeitzone:"
"Time Zone:": "Zeitzone:",
"API": "API",
"Document ID copied to clipboard": "Dokument-ID in die Zwischenablage kopiert",
"Ok": "Ok"
},
"DocumentUsage": {
"Attachments Size": "Anhänge Größe",
@ -649,7 +653,8 @@
"Return to viewing as yourself": "Zurück zur Selbstdarstellung",
"TOOLS": "WERKZEUGE",
"Tour of this Document": "Tour durch dieses Dokument",
"Validate Data": "Daten validieren"
"Validate Data": "Daten validieren",
"Settings": "Einstellungen"
},
"TopBar": {
"Manage Team": "Team verwalten"
@ -666,12 +671,12 @@
"Current field ": "Aktuelles Feld ",
"OK": "OK"
},
"TypeTransformation": {
"TypeTransform": {
"Apply": "Anwenden",
"Cancel": "Abbrechen",
"Preview": "Vorschau",
"Revise": "Überarbeiten",
"Update formula (Shift+Enter)": "Formel aktualisieren (Umschalttaste+Eingabetaste)"
"Update formula (Shift+Enter)": "Formel aktualisieren (Umschalttaste+Eingabetaste)",
"Revise": "Überarbeiten"
},
"UserManagerModel": {
"Editor": "Redakteur",
@ -834,11 +839,125 @@
"Users from table": "Benutzer aus der Tabelle",
"View As": "Anzeigen als"
},
"TypeTransform": {
"Apply": "Anwenden",
"Cancel": "Abbrechen",
"Preview": "Vorschau",
"TypeTransformation": {
"Update formula (Shift+Enter)": "Formel aktualisieren (Umschalttaste+Eingabetaste)",
"Revise": "Überarbeiten"
"Cancel": "Abbrechen",
"Revise": "Überarbeiten",
"Preview": "Vorschau",
"Apply": "Anwenden"
},
"CellStyle": {
"CELL STYLE": "ZELLENSTIL",
"Open row styles": "Zeilenstile öffnen",
"Cell Style": "Zellenstil",
"Default cell style": "Standard-Zellenstil",
"Mixed style": "Gemischter Stil"
},
"DiscussionEditor": {
"Resolve": "Beschließen",
"Save": "Speichern",
"Show resolved comments": "Gelöste Kommentare anzeigen",
"Only my threads": "Nur meine Fäden",
"Open": "Öffnen",
"Remove": "Entfernen",
"Reply to a comment": "Auf einen Kommentar antworten",
"Reply": "Antwort",
"Comment": "Kommentar",
"Edit": "Bearbeiten",
"Only current page": "Nur aktuelle Seite",
"Started discussion": "Begonnene Diskussion",
"Write a comment": "Schreiben Sie einen Kommentar",
"Marked as resolved": "Markiert als gelöst",
"Cancel": "Abbrechen",
"Showing last {{nb}} comments": "Letzte {{nb}} Kommentare anzeigen"
},
"ColumnInfo": {
"COLUMN DESCRIPTION": "SPALTENBESCHREIBUNG",
"COLUMN ID: ": "SPALTEN-ID: ",
"Save": "Speichern",
"COLUMN LABEL": "SPALTENBEZEICHNUNG",
"Cancel": "Abbrechen"
},
"ChoiceTextBox": {
"CHOICES": "WAHLEN"
},
"ColumnEditor": {
"COLUMN DESCRIPTION": "SPALTENBESCHREIBUNG",
"COLUMN LABEL": "SPALTENBEZEICHNUNG"
},
"ConditionalStyle": {
"Add conditional style": "Bedingten Stil hinzufügen",
"Error in style rule": "Fehler in der Stilregel",
"Rule must return True or False": "Regel muss wahr oder falsch zurückgeben",
"Add another rule": "Eine weitere Regel hinzufügen",
"Row Style": "Zeilenstil"
},
"CurrencyPicker": {
"Invalid currency": "Ungültige Währung"
},
"FieldBuilder": {
"Changing multiple column types": "Mehrere Spaltentypen ändern",
"Mixed format": "Gemischtes Format",
"Mixed types": "Gemischte Typen",
"Revert field settings for {{colId}} to common": "Feldeinstellungen für {{colId}} auf \"Allgemein\" zurücksetzen",
"Apply Formula to Data": "Formel auf Daten anwenden",
"CELL FORMAT": "ZELLENFORMAT",
"DATA FROM TABLE": "DATEN AUS TABELLE",
"Save field settings for {{colId}} as common": "Feldeinstellungen für {{colId}} als Algemein speichern",
"Use separate field settings for {{colId}}": "Verwenden Sie separate Feldeinstellungen für {{colId}}"
},
"EditorTooltip": {
"Convert column to formula": "Spalte in Formel umwandeln"
},
"FormulaEditor": {
"Column or field is required": "Spalte oder Feld ist erforderlich",
"Error in the cell": "Fehler in der Zelle",
"Errors in all {{numErrors}} cells": "Fehler in allen {{numErrors}} Zellen",
"editingFormula is required": "Bearbeitungsformel ist erforderlich",
"Errors in {{numErrors}} of {{numCells}} cells": "Fehler in {{numErrors}} von {{numCells}} Zellen"
},
"Reference": {
"SHOW COLUMN": "SPALTE ANZEIGEN",
"CELL FORMAT": "ZELLENFORMAT",
"Row ID": "Zeilen-ID"
},
"HyperLinkEditor": {
"[link label] url": "[Linklabel]-URL"
},
"welcomeTour": {
"Add New": "Neu hinzufügen",
"Building up": "Zubauend",
"Configuring your document": "Konfigurieren Ihres Dokuments",
"Help Center": "Hilfe-Center",
"Sharing": "Teilen",
"Welcome to Grist!": "Willkommen bei Grist!",
"Enter": "Eingabe",
"Customizing columns": "Anpassen von Spalten",
"Browse our {{templateLibrary}} to discover what's possible and get inspired.": "Durchsuchen Sie unsere {{templateLibrary}}, um zu entdecken, was möglich ist und sich inspirieren lassen.",
"Double-click or hit {{enter}} on a cell to edit it. ": "Doppelklicken oder {{enter}} auf eine Zelle drücken, um sie zu bearbeiten. ",
"Editing Data": "Bearbeiten von Daten",
"Flying higher": "Höher fliegen",
"Share": "Teilen",
"Reference": "Referenz",
"Make it relational! Use the {{ref}} type to link tables. ": "Machen Sie es relativ! Verwenden Sie den {{ref}}-Typ, um Tabellen zu verlinken. ",
"Start with {{equal}} to enter a formula.": "Beginnen Sie mit {{equal}}, um eine Formel einzugeben.",
"Set formatting options, formulas, or column types, such as dates, choices, or attachments. ": "Legen Sie Formatierungsoptionen, Formeln oder Spaltentypen fest, z. B. Daten, Auswahlmöglichkeiten oder Anhänge. ",
"Toggle the {{creatorPanel}} to format columns, ": "Schalten Sie die {{creatorPanel}} an, um Spalten zu formatieren, ",
"Use the Share button ({{share}}) to share the document or export data.": "Verwenden Sie die Schaltfläche Teilen ({{share}}), um das Dokument zu teilen oder Daten zu exportieren.",
"Use {{addNew}} to add widgets, pages, or import more data. ": "Verwenden Sie {{addNew}}, um Widgets und Seiten hinzuzufügen oder weitere Daten zu importieren. ",
"Use {{helpCenter}} for documentation or questions.": "Verwenden Sie {{helpCenter}} für Dokumentation oder Fragen.",
"convert to card view, select data, and more.": "in die Kartenansicht konvertieren, Daten auswählen und vieles mehr.",
"creator panel": "Ersteller-Panel",
"template library": "Vorlagenbibliothek"
},
"NumericTextBox": {
"Currency": "Währung",
"Decimals": "Dezimalstellen",
"Default currency ({{defaultCurrency}})": "Standardwährung ({{defaultCurrency}})",
"Number Format": "Zahlenformat"
},
"FieldEditor": {
"It should be impossible to save a plain data value into a formula column": "Es sollte unmöglich sein, einen einfachen Datenwert in eine Formelspalte zu speichern",
"Unable to finish saving edited cell": "Speichern der bearbeiteten Zelle kann nicht abgeschlossen werden"
}
}

View File

@ -38,7 +38,8 @@
"User Attributes": "User Attributes",
"View As": "View As",
"Seed rules": "Seed rules",
"When adding table rules, automatically add a rule to grant OWNER full access.": "When adding table rules, automatically add a rule to grant OWNER full access."
"When adding table rules, automatically add a rule to grant OWNER full access.": "When adding table rules, automatically add a rule to grant OWNER full access.",
"Permission to edit document structure": "Permission to edit document structure"
},
"AccountPage": {
"API": "API",
@ -603,7 +604,8 @@
"Return to viewing as yourself": "Return to viewing as yourself",
"TOOLS": "TOOLS",
"Tour of this Document": "Tour of this Document",
"Validate Data": "Validate Data"
"Validate Data": "Validate Data",
"Settings": "Settings"
},
"TopBar": {
"Manage Team": "Manage Team"
@ -779,5 +781,119 @@
"Preview": "Preview",
"Revise": "Revise",
"Update formula (Shift+Enter)": "Update formula (Shift+Enter)"
},
"CellStyle": {
"CELL STYLE": "CELL STYLE",
"Cell Style": "Cell Style",
"Default cell style": "Default cell style",
"Mixed style": "Mixed style",
"Open row styles": "Open row styles"
},
"ChoiceTextBox": {
"CHOICES": "CHOICES"
},
"ColumnEditor": {
"COLUMN DESCRIPTION": "COLUMN DESCRIPTION",
"COLUMN LABEL": "COLUMN LABEL"
},
"ColumnInfo": {
"COLUMN DESCRIPTION": "COLUMN DESCRIPTION",
"COLUMN ID: ": "COLUMN ID: ",
"COLUMN LABEL": "COLUMN LABEL",
"Cancel": "Cancel",
"Save": "Save"
},
"ConditionalStyle": {
"Add another rule": "Add another rule",
"Add conditional style": "Add conditional style",
"Error in style rule": "Error in style rule",
"Row Style": "Row Style",
"Rule must return True or False": "Rule must return True or False"
},
"CurrencyPicker": {
"Invalid currency": "Invalid currency"
},
"DiscussionEditor": {
"Cancel": "Cancel",
"Comment": "Comment",
"Edit": "Edit",
"Marked as resolved": "Marked as resolved",
"Only current page": "Only current page",
"Only my threads": "Only my threads",
"Open": "Open",
"Remove": "Remove",
"Reply": "Reply",
"Reply to a comment": "Reply to a comment",
"Resolve": "Resolve",
"Save": "Save",
"Show resolved comments": "Show resolved comments",
"Showing last {{nb}} comments": "Showing last {{nb}} comments",
"Started discussion": "Started discussion",
"Write a comment": "Write a comment"
},
"EditorTooltip": {
"Convert column to formula": "Convert column to formula"
},
"FieldBuilder": {
"Apply Formula to Data": "Apply Formula to Data",
"CELL FORMAT": "CELL FORMAT",
"Changing multiple column types": "Changing multiple column types",
"DATA FROM TABLE": "DATA FROM TABLE",
"Mixed format": "Mixed format",
"Mixed types": "Mixed types",
"Revert field settings for {{colId}} to common": "Revert field settings for {{colId}} to common",
"Save field settings for {{colId}} as common": "Save field settings for {{colId}} as common",
"Use separate field settings for {{colId}}": "Use separate field settings for {{colId}}"
},
"FieldEditor": {
"It should be impossible to save a plain data value into a formula column": "It should be impossible to save a plain data value into a formula column",
"Unable to finish saving edited cell": "Unable to finish saving edited cell"
},
"FormulaEditor": {
"Column or field is required": "Column or field is required",
"Error in the cell": "Error in the cell",
"Errors in all {{numErrors}} cells": "Errors in all {{numErrors}} cells",
"Errors in {{numErrors}} of {{numCells}} cells": "Errors in {{numErrors}} of {{numCells}} cells",
"editingFormula is required": "editingFormula is required"
},
"HyperLinkEditor": {
"[link label] url": "[link label] url"
},
"NumericTextBox": {
"Currency": "Currency",
"Decimals": "Decimals",
"Default currency ({{defaultCurrency}})": "Default currency ({{defaultCurrency}})",
"Number Format": "Number Format"
},
"Reference": {
"CELL FORMAT": "CELL FORMAT",
"Row ID": "Row ID",
"SHOW COLUMN": "SHOW COLUMN"
},
"welcomeTour": {
"Add New": "Add New",
"Browse our {{templateLibrary}} to discover what's possible and get inspired.": "Browse our {{templateLibrary}} to discover what's possible and get inspired.",
"Building up": "Building up",
"Configuring your document": "Configuring your document",
"Customizing columns": "Customizing columns",
"Double-click or hit {{enter}} on a cell to edit it. ": "Double-click or hit {{enter}} on a cell to edit it. ",
"Editing Data": "Editing Data",
"Enter": "Enter",
"Flying higher": "Flying higher",
"Help Center": "Help Center",
"Make it relational! Use the {{ref}} type to link tables. ": "Make it relational! Use the {{ref}} type to link tables. ",
"Reference": "Reference",
"Set formatting options, formulas, or column types, such as dates, choices, or attachments. ": "Set formatting options, formulas, or column types, such as dates, choices, or attachments. ",
"Share": "Share",
"Sharing": "Sharing",
"Start with {{equal}} to enter a formula.": "Start with {{equal}} to enter a formula.",
"Toggle the {{creatorPanel}} to format columns, ": "Toggle the {{creatorPanel}} to format columns, ",
"Use the Share button ({{share}}) to share the document or export data.": "Use the Share button ({{share}}) to share the document or export data.",
"Use {{addNew}} to add widgets, pages, or import more data. ": "Use {{addNew}} to add widgets, pages, or import more data. ",
"Use {{helpCenter}} for documentation or questions.": "Use {{helpCenter}} for documentation or questions.",
"Welcome to Grist!": "Welcome to Grist!",
"convert to card view, select data, and more.": "convert to card view, select data, and more.",
"creator panel": "creator panel",
"template library": "template library"
}
}

View File

@ -34,7 +34,8 @@
"Special Rules": "Reglas especiales",
"View As": "Ver como",
"Seed rules": "Reglas de semillas",
"When adding table rules, automatically add a rule to grant OWNER full access.": "Al agregar reglas de tabla, agregue automáticamente una regla para otorgar acceso completo al PROPIETARIO."
"When adding table rules, automatically add a rule to grant OWNER full access.": "Al agregar reglas de tabla, agregue automáticamente una regla para otorgar acceso completo al PROPIETARIO.",
"Permission to edit document structure": "Permiso para editar la estructura del documento"
},
"AccountPage": {
"API": "API",
@ -223,7 +224,10 @@
"Save": "Guardar",
"Save and Reload": "Guardar y recargar",
"This document's ID (for API use):": "ID de este documento (para uso de API):",
"Time Zone:": "Zona horaria:"
"Time Zone:": "Zona horaria:",
"Ok": "Ok",
"Document ID copied to clipboard": "ID de documento copiado al portapapeles",
"API": "API"
},
"DuplicateTable": {
"Copy all data in addition to the table structure.": "Copiar todos los datos además de la estructura de la tabla.",
@ -543,7 +547,8 @@
"Return to viewing as yourself": "Volver a ver como usted mismo",
"TOOLS": "HERRAMIENTAS",
"Tour of this Document": "Recorrido por este documento",
"Validate Data": "Validar datos"
"Validate Data": "Validar datos",
"Settings": "Ajustes"
},
"TopBar": {
"Manage Team": "Administrar equipo"
@ -768,12 +773,12 @@
"SelectionSummary": {
"Copied to clipboard": "Copiado al portapapeles"
},
"TypeTransformation": {
"TypeTransform": {
"Apply": "Aplicar",
"Cancel": "Cancelar",
"Preview": "Vista previa",
"Revise": "Revisar",
"Update formula (Shift+Enter)": "Actualizar fórmula (Mayús+Intro)"
"Update formula (Shift+Enter)": "Actualizar fórmula (Mayús+Intro)",
"Preview": "Vista previa"
},
"UserManagerModel": {
"Editor": "Editor",
@ -824,11 +829,125 @@
"View As": "Ver como",
"Example Users": "Usuarios de ejemplo"
},
"TypeTransform": {
"Apply": "Aplicar",
"TypeTransformation": {
"Update formula (Shift+Enter)": "Actualizar fórmula (Mayús+Intro)",
"Cancel": "Cancelar",
"Revise": "Revisar",
"Update formula (Shift+Enter)": "Actualizar fórmula (Mayús+Intro)",
"Apply": "Aplicar",
"Preview": "Vista previa"
},
"CellStyle": {
"Cell Style": "Estilo de celda",
"Default cell style": "Estilo de celda predeterminado",
"CELL STYLE": "ESTILO DE CELDA",
"Open row styles": "Abrir estilos de fila",
"Mixed style": "Estilo mixto"
},
"ColumnInfo": {
"Cancel": "Cancelar",
"Save": "Guardar",
"COLUMN DESCRIPTION": "DESCRIPCIÓN DE LA COLUMNA",
"COLUMN ID: ": "ID DE COLUMNA: ",
"COLUMN LABEL": "ETIQUETA DE COLUMNA"
},
"FieldBuilder": {
"Revert field settings for {{colId}} to common": "Revertir la configuración de campo de {{colId}} a común",
"Use separate field settings for {{colId}}": "Utilice configuraciones de campo separadas para {{colId}}",
"Save field settings for {{colId}} as common": "Guardar configuración de campo de {{colId}} como común",
"DATA FROM TABLE": "DATOS DE LA TABLA",
"Mixed types": "Tipos mixtos",
"Apply Formula to Data": "Aplicar Fórmula a Datos",
"CELL FORMAT": "FORMATO DE CELDA",
"Changing multiple column types": "Cambiar varios tipos de columna",
"Mixed format": "Formato mixto"
},
"CurrencyPicker": {
"Invalid currency": "Moneda inválida"
},
"DiscussionEditor": {
"Cancel": "Cancelar",
"Edit": "Editar",
"Only current page": "Sólo página actual",
"Remove": "Quitar",
"Resolve": "Resolver",
"Save": "Guardar",
"Started discussion": "Discusión iniciada",
"Show resolved comments": "Mostrar comentarios resueltos",
"Write a comment": "Escribe un comentario",
"Marked as resolved": "Marcado como resuelto",
"Only my threads": "Sólo mis hilos",
"Reply": "Respuesta",
"Comment": "Comentario",
"Open": "Abrir",
"Reply to a comment": "Responder a un comentario",
"Showing last {{nb}} comments": "Mostrando los últimos {{nb}} comentarios"
},
"EditorTooltip": {
"Convert column to formula": "Convertir columna en fórmula"
},
"FormulaEditor": {
"Errors in {{numErrors}} of {{numCells}} cells": "Errores en {{numErrors}} de {{numCells}} celdas",
"Column or field is required": "Se requiere columna o campo",
"Error in the cell": "Error en la celda",
"Errors in all {{numErrors}} cells": "Errores en todas las {{numErrors}} celdas",
"editingFormula is required": "ediciónFórmula es necesaria"
},
"welcomeTour": {
"Add New": "Agregar Nuevo",
"Configuring your document": "Configurando tu documento",
"Enter": "Intro",
"Flying higher": "Volando más alto",
"Reference": "Referencia",
"Start with {{equal}} to enter a formula.": "Comience con {{equal}} para introducir una fórmula.",
"Toggle the {{creatorPanel}} to format columns, ": "Active {{creatorPanel}} para dar formato a las columnas, ",
"Welcome to Grist!": "¡Bienvenido a Grist!",
"template library": "biblioteca de plantillas",
"creator panel": "panel creador",
"Sharing": "Compartiendo",
"Help Center": "Centro de ayuda",
"Building up": "Construyendo",
"Customizing columns": "Personalizando columnas",
"Double-click or hit {{enter}} on a cell to edit it. ": "Haga doble clic o pulse {{enter}} en una celda para editarla. ",
"Browse our {{templateLibrary}} to discover what's possible and get inspired.": "Explore nuestro {{templateLibrary}} para descubrir lo que es posible y sentirse inspirado.",
"Editing Data": "Editando datos",
"Make it relational! Use the {{ref}} type to link tables. ": "¡Hazlo relacional! Utilice el tipo {{ref}} para vincular tablas. ",
"Set formatting options, formulas, or column types, such as dates, choices, or attachments. ": "Establezca opciones de formato, fórmulas o tipos de columnas, como fechas, opciones o anexos. ",
"Share": "Compartir",
"Use the Share button ({{share}}) to share the document or export data.": "Utilice el botón Compartir ({{share}}) para compartir el documento o exportar los datos.",
"Use {{helpCenter}} for documentation or questions.": "Utilice {{helpCenter}} para documentación o preguntas.",
"Use {{addNew}} to add widgets, pages, or import more data. ": "Utilice {{addNew}} para añadir widgets, páginas o importar más datos. ",
"convert to card view, select data, and more.": "convertir a la vista de la tarjeta, seleccionar datos y más."
},
"HyperLinkEditor": {
"[link label] url": "[etiqueta de enlace] url"
},
"NumericTextBox": {
"Currency": "Moneda",
"Default currency ({{defaultCurrency}})": "Moneda predeterminada ({{defaultCurrency}})",
"Number Format": "Formato de número",
"Decimals": "Decimales"
},
"ChoiceTextBox": {
"CHOICES": "OPCIONES"
},
"ColumnEditor": {
"COLUMN DESCRIPTION": "DESCRIPCIÓN DE LA COLUMNA",
"COLUMN LABEL": "ETIQUETA DE COLUMNA"
},
"FieldEditor": {
"Unable to finish saving edited cell": "No se puede terminar de guardar la celda editada",
"It should be impossible to save a plain data value into a formula column": "Debería ser imposible guardar un valor de datos plano en una columna de fórmulas"
},
"ConditionalStyle": {
"Add another rule": "Añadir otra regla",
"Error in style rule": "Error en la regla de estilo",
"Rule must return True or False": "La regla debe regresar Verdadera o Falsa",
"Add conditional style": "Añadir estilo condicional",
"Row Style": "Estilo de fila"
},
"Reference": {
"SHOW COLUMN": "MOSTRAR COLUMNA",
"CELL FORMAT": "FORMATO DE CELDA",
"Row ID": "ID de fila"
}
}

View File

@ -610,7 +610,7 @@
"Cancel": "Annuler",
"Close": "Fermer"
},
"TypeTransformation": {
"TypeTransform": {
"Apply": "Appliquer",
"Cancel": "Annuler",
"Preview": "Aperçu",

View File

@ -39,7 +39,8 @@
"Users": "Usuários",
"View As": "Ver como",
"Seed rules": "Regras de propagação",
"When adding table rules, automatically add a rule to grant OWNER full access.": "Ao adicionar regras de tabela, adicione automaticamente uma regra para conceder ao PROPRIETÁRIO acesso total."
"When adding table rules, automatically add a rule to grant OWNER full access.": "Ao adicionar regras de tabela, adicione automaticamente uma regra para conceder ao PROPRIETÁRIO acesso total.",
"Permission to edit document structure": "Permissão para editar a estrutura do documento"
},
"AccountPage": {
"API": "API",
@ -274,7 +275,10 @@
"Save": "Salvar",
"Save and Reload": "Salvar e Recarregar",
"This document's ID (for API use):": "O ID deste documento (para uso em API):",
"Time Zone:": "Fuso horário:"
"Time Zone:": "Fuso horário:",
"Ok": "Ok",
"Document ID copied to clipboard": "ID do documento copiado para a área de transferência",
"API": "API"
},
"DocumentUsage": {
"Attachments Size": "Tamanho dos Anexos",
@ -649,7 +653,8 @@
"Return to viewing as yourself": "Voltar a ver como você mesmo",
"TOOLS": "FERRAMENTAS",
"Tour of this Document": "Tour desse Documento",
"Validate Data": "Validar dados"
"Validate Data": "Validar dados",
"Settings": "Configurações"
},
"TopBar": {
"Manage Team": "Gerenciar Equipe"
@ -666,7 +671,7 @@
"Current field ": "Campo atual ",
"OK": "OK"
},
"TypeTransformation": {
"TypeTransform": {
"Apply": "Aplicar",
"Cancel": "Cancelar",
"Preview": "Pré-visualização",
@ -834,11 +839,125 @@
"View As": "Ver como",
"Example Users": "Usuários de exemplo"
},
"TypeTransform": {
"Apply": "Aplicar",
"welcomeTour": {
"Use {{helpCenter}} for documentation or questions.": "Use {{helpCenter}} para documentação ou perguntas.",
"convert to card view, select data, and more.": "converta para a visualização de cartão, selecione dados e muito mais.",
"Start with {{equal}} to enter a formula.": "Comece com {{equal}} para inserir uma fórmula.",
"Welcome to Grist!": "Bem-vindo ao Grist!",
"template library": "biblioteca de modelos",
"Flying higher": "Voando mais alto",
"Add New": "Adicionar Novo",
"Building up": "Construindo",
"Customizing columns": "Personalizando colunas",
"Configuring your document": "Configurando seu documento",
"Make it relational! Use the {{ref}} type to link tables. ": "Faça-o relacional! Use o tipo {{ref}} para vincular tabelas. ",
"Browse our {{templateLibrary}} to discover what's possible and get inspired.": "Procure nosso {{templateLibrary}} para descobrir o que é possível e se inspirar.",
"Double-click or hit {{enter}} on a cell to edit it. ": "Clique duas vezes ou pressione {{enter}} em uma célula para editá-la. ",
"Editing Data": "Editando dados",
"Enter": "Entra",
"Help Center": "Centro de Ajuda",
"Reference": "Referência",
"Set formatting options, formulas, or column types, such as dates, choices, or attachments. ": "Defina opções de formatação, fórmulas ou tipos de coluna, como datas, escolhas ou anexos. ",
"Share": "Compartilhar",
"Sharing": "Compartilhando",
"Toggle the {{creatorPanel}} to format columns, ": "Alternar o {{creatorPanel}} para formatar colunas, ",
"Use {{addNew}} to add widgets, pages, or import more data. ": "Use {{addNew}} para adicionar widgets, páginas ou importar mais dados. ",
"creator panel": "painel do criador",
"Use the Share button ({{share}}) to share the document or export data.": "Use o botão Compartilhar ({{share}}) para compartilhar o documento ou exportar dados."
},
"ColumnInfo": {
"COLUMN LABEL": "RÓTULO DA COLUNA",
"Cancel": "Cancelar",
"Preview": "Pré-visualização",
"Save": "Salvar",
"COLUMN DESCRIPTION": "DESCRIÇÃO DA COLUNA",
"COLUMN ID: ": "ID DA COLUNA: "
},
"ConditionalStyle": {
"Row Style": "Estilo de Linha",
"Rule must return True or False": "A regra deve retornar Verdadeiro ou Falso",
"Error in style rule": "Erro na regra de estilo",
"Add another rule": "Adicionar outra regra",
"Add conditional style": "Adicionar estilo condicional"
},
"CurrencyPicker": {
"Invalid currency": "Moeda inválida"
},
"DiscussionEditor": {
"Cancel": "Cancelar",
"Marked as resolved": "Marcado como resolvido",
"Reply": "Responder",
"Reply to a comment": "Responder a um comentário",
"Write a comment": "Escreva um comentário",
"Comment": "Comentário",
"Resolve": "Resolver",
"Started discussion": "Discussão iniciada",
"Edit": "Editar",
"Only current page": "Somente a página atual",
"Only my threads": "Somente meus tópicos",
"Showing last {{nb}} comments": "Mostrar os últimos {{nb}} comentários",
"Open": "Abrir",
"Remove": "Remover",
"Save": "Salvar",
"Show resolved comments": "Mostrar comentários resolvidos"
},
"FieldBuilder": {
"CELL FORMAT": "FORMATO DA CÉLULA",
"DATA FROM TABLE": "DADOS DA TABELA",
"Apply Formula to Data": "Aplicar fórmula aos dados",
"Changing multiple column types": "Alterar vários tipos de colunas",
"Mixed format": "Formato misto",
"Save field settings for {{colId}} as common": "Salvar configurações de campo da {{colId}} como comum",
"Revert field settings for {{colId}} to common": "Reverter configurações de campo da {{colId}} para comum",
"Mixed types": "Tipos mistos",
"Use separate field settings for {{colId}}": "Use configurações de campo separadas para {{colId}}"
},
"FormulaEditor": {
"Column or field is required": "Coluna ou campo é obrigatório",
"editingFormula is required": "ediçãoFórmula é obrigatório",
"Errors in all {{numErrors}} cells": "Erro em todas as {{numErrors}} células",
"Errors in {{numErrors}} of {{numCells}} cells": "Erros em {{numErrors}} de {{numCells}} células",
"Error in the cell": "Erro na célula"
},
"HyperLinkEditor": {
"[link label] url": "[rótulo do link] url"
},
"NumericTextBox": {
"Currency": "Moeda",
"Decimals": "Decimais",
"Default currency ({{defaultCurrency}})": "Moeda padrão ({{defaultCurrency}})",
"Number Format": "Formato de número"
},
"TypeTransformation": {
"Preview": "Prévisualizar",
"Apply": "Aplicar",
"Revise": "Revisar",
"Cancel": "Cancelar",
"Update formula (Shift+Enter)": "Atualizar a fórmula (Shift+Enter)"
},
"CellStyle": {
"CELL STYLE": "ESTILO DE CÉLULA",
"Cell Style": "Estilo de célula",
"Default cell style": "Estilo de célula padrão",
"Mixed style": "Estilo misto",
"Open row styles": "Estilos de linha aberta"
},
"ColumnEditor": {
"COLUMN DESCRIPTION": "DESCRIÇÃO DA COLUNA",
"COLUMN LABEL": "RÓTULO DA COLUNA"
},
"FieldEditor": {
"Unable to finish saving edited cell": "Não é possível concluir o salvamento da célula editada",
"It should be impossible to save a plain data value into a formula column": "Deveria ser impossível salvar um valor de dados simples em uma coluna de fórmula"
},
"EditorTooltip": {
"Convert column to formula": "Converter coluna em fórmula"
},
"Reference": {
"Row ID": "ID da linha",
"CELL FORMAT": "FORMATO DA CÉLULA",
"SHOW COLUMN": "MOSTRAR COLUNA"
},
"ChoiceTextBox": {
"CHOICES": "ESCOLHAS"
}
}