(core) Makes GristTooltips translatable

Test Plan: Should no break anything

Reviewers: jarek

Reviewed By: jarek

Differential Revision: https://phab.getgrist.com/D3785
This commit is contained in:
Cyprien P 2023-01-31 17:35:46 +01:00
parent ab2e2ef402
commit ef0a55ced1
4 changed files with 107 additions and 62 deletions

View File

@ -90,7 +90,7 @@ export class BehavioralPromptsManager extends Disposable {
const {hideArrow = false, onDispose, popupOptions} = options;
const {title, content} = GristBehavioralPrompts[prompt];
const ctl = showBehavioralPrompt(refElement, title, content(), {
const ctl = showBehavioralPrompt(refElement, title(), content(), {
onClose: (dontShowTips) => {
if (dontShowTips) { this._dontShowTips(); }
this._markAsSeen(prompt);

View File

@ -2,7 +2,10 @@ import {cssLink} from 'app/client/ui2018/links';
import {commonUrls} from 'app/common/gristUrls';
import {BehavioralPrompt} from 'app/common/Prefs';
import {dom, DomContents, DomElementArg, styled} from 'grainjs';
import { icon } from '../ui2018/icons';
import {icon} from 'app/client/ui2018/icons';
import {makeT} from 'app/client/lib/localization';
const t = makeT('GristTooltips');
const cssTooltipContent = styled('div', `
display: flex;
@ -34,36 +37,35 @@ export type Tooltip =
export type TooltipContentFunc = (...domArgs: DomElementArg[]) => DomContents;
// TODO: i18n
export const GristTooltips: Record<Tooltip, TooltipContentFunc> = {
dataSize: (...args: DomElementArg[]) => cssTooltipContent(
dom('div', 'The total size of all data in this document, excluding attachments.'),
dom('div', 'Updates every 5 minutes.'),
dom('div', t('The total size of all data in this document, excluding attachments.')),
dom('div', t('Updates every 5 minutes.')),
...args,
),
setTriggerFormula: (...args: DomElementArg[]) => cssTooltipContent(
dom('div',
'Formulas that trigger in certain cases, and store the calculated value as data.'
t('Formulas that trigger in certain cases, and store the calculated value as data.')
),
dom('div',
'Useful for storing the timestamp or author of a new record, data cleaning, and '
+ 'more.'
t('Useful for storing the timestamp or author of a new record, data cleaning, and '
+ 'more.')
),
dom('div',
cssLink({href: commonUrls.helpTriggerFormulas, target: '_blank'}, 'Learn more.'),
cssLink({href: commonUrls.helpTriggerFormulas, target: '_blank'}, t('Learn more.')),
),
...args,
),
selectBy: (...args: DomElementArg[]) => cssTooltipContent(
dom('div', 'Link your new widget to an existing widget on this page.'),
dom('div', t('Link your new widget to an existing widget on this page.')),
dom('div',
cssLink({href: commonUrls.helpLinkingWidgets, target: '_blank'}, 'Learn more.'),
cssLink({href: commonUrls.helpLinkingWidgets, target: '_blank'}, t('Learn more.')),
),
...args,
),
workOnACopy: (...args: DomElementArg[]) => cssTooltipContent(
dom('div',
'Try out changes in a copy, then decide whether to replace the original with your edits.'
t('Try out changes in a copy, then decide whether to replace the original with your edits.')
),
dom('div',
cssLink({href: commonUrls.helpTryingOutChanges, target: '_blank'}, 'Learn more.'),
@ -72,127 +74,131 @@ export const GristTooltips: Record<Tooltip, TooltipContentFunc> = {
),
openAccessRules: (...args: DomElementArg[]) => cssTooltipContent(
dom('div',
'Access rules give you the power to create nuanced rules to determine who can '
+ 'see or edit which parts of your document.'
t('Access rules give you the power to create nuanced rules to determine who can '
+ 'see or edit which parts of your document.')
),
dom('div',
cssLink({href: commonUrls.helpAccessRules, target: '_blank'}, 'Learn more.'),
cssLink({href: commonUrls.helpAccessRules, target: '_blank'}, t('Learn more.')),
),
...args,
),
addRowConditionalStyle: (...args: DomElementArg[]) => cssTooltipContent(
dom('div', 'Apply conditional formatting to rows based on formulas.'),
dom('div', t('Apply conditional formatting to rows based on formulas.')),
dom('div',
cssLink({href: commonUrls.helpConditionalFormatting, target: '_blank'}, 'Learn more.'),
cssLink({href: commonUrls.helpConditionalFormatting, target: '_blank'}, t('Learn more.')),
),
...args,
),
addColumnConditionalStyle: (...args: DomElementArg[]) => cssTooltipContent(
dom('div', 'Apply conditional formatting to cells in this column when formula conditions are met.'),
dom('div', 'Click on “Open row styles” to apply conditional formatting to rows.'),
dom('div', t('Apply conditional formatting to cells in this column when formula conditions are met.')),
dom('div', t('Click on “Open row styles” to apply conditional formatting to rows.')),
dom('div',
cssLink({href: commonUrls.helpConditionalFormatting, target: '_blank'}, 'Learn more.'),
cssLink({href: commonUrls.helpConditionalFormatting, target: '_blank'}, t('Learn more.')),
),
...args,
),
};
export interface BehavioralPromptContent {
title: string;
title: () => string;
content: (...domArgs: DomElementArg[]) => DomContents;
}
// TODO: i18n
export const GristBehavioralPrompts: Record<BehavioralPrompt, BehavioralPromptContent> = {
referenceColumns: {
title: 'Reference Columns',
title: () => t('Reference Columns'),
content: (...args: DomElementArg[]) => cssTooltipContent(
dom('div', 'Reference columns are the key to ', cssBoldText('relational'), ' data in Grist.'),
dom('div', 'They allow for one record to point (or refer) to another.'),
dom('div', t('Reference columns are the key to {{relational}} data in Grist.', {
relational: cssBoldText(t('relational'))
})),
dom('div', t('They allow for one record to point (or refer) to another.')),
dom('div',
cssLink({href: commonUrls.helpColRefs, target: '_blank'}, 'Learn more.'),
cssLink({href: commonUrls.helpColRefs, target: '_blank'}, t('Learn more.')),
),
...args,
),
},
referenceColumnsConfig: {
title: 'Reference Columns',
title: () => t('Reference Columns'),
content: (...args: DomElementArg[]) => cssTooltipContent(
dom('div', 'Select the table to link to.'),
dom('div', 'Cells in a reference column always identify an ', cssItalicizedText('entire'),
' record in that table, but you may select which column from that record to show.'),
dom('div', t('Select the table to link to.')),
dom('div', t('Cells in a reference column always identify an {{entire}} ' +
'record in that table, but you may select which column from that record to show.', {
entire: cssItalicizedText(t('entire'))
})),
dom('div',
cssLink({href: commonUrls.helpUnderstandingReferenceColumns, target: '_blank'}, 'Learn more.'),
cssLink({href: commonUrls.helpUnderstandingReferenceColumns, target: '_blank'}, t('Learn more.')),
),
...args,
),
},
rawDataPage: {
title: 'Raw Data page',
title: () => t('Raw Data page'),
content: (...args: DomElementArg[]) => cssTooltipContent(
dom('div', 'The Raw Data page lists all data tables in your document, '
+ 'including summary tables and tables not included in page layouts.'),
dom('div', cssLink({href: commonUrls.helpRawData, target: '_blank'}, 'Learn more.')),
dom('div', t('The Raw Data page lists all data tables in your document, '
+ 'including summary tables and tables not included in page layouts.')),
dom('div', cssLink({href: commonUrls.helpRawData, target: '_blank'}, t('Learn more.'))),
...args,
),
},
accessRules: {
title: 'Access Rules',
title: () => t('Access Rules'),
content: (...args: DomElementArg[]) => cssTooltipContent(
dom('div', 'Access rules give you the power to create nuanced rules '
+ 'to determine who can see or edit which parts of your document.'),
dom('div', cssLink({href: commonUrls.helpAccessRules, target: '_blank'}, 'Learn more.')),
dom('div', t('Access rules give you the power to create nuanced rules '
+ 'to determine who can see or edit which parts of your document.')),
dom('div', cssLink({href: commonUrls.helpAccessRules, target: '_blank'}, t('Learn more.'))),
...args,
),
},
filterButtons: {
title: 'Pinning Filters',
title: () => t('Pinning Filters'),
content: (...args: DomElementArg[]) => cssTooltipContent(
dom('div', 'Pinned filters are displayed as buttons above the widget.'),
dom('div', 'Unpin to hide the the button while keeping the filter.'),
dom('div', cssLink({href: commonUrls.helpFilterButtons, target: '_blank'}, 'Learn more.')),
dom('div', t('Pinned filters are displayed as buttons above the widget.')),
dom('div', t('Unpin to hide the the button while keeping the filter.')),
dom('div', cssLink({href: commonUrls.helpFilterButtons, target: '_blank'}, t('Learn more.'))),
...args,
),
},
nestedFiltering: {
title: 'Nested Filtering',
title: () => t('Nested Filtering'),
content: (...args: DomElementArg[]) => cssTooltipContent(
dom('div', 'You can filter by more than one column.'),
dom('div', 'Only those rows will appear which match all of the filters.'),
dom('div', t('You can filter by more than one column.')),
dom('div', t('Only those rows will appear which match all of the filters.')),
...args,
),
},
pageWidgetPicker: {
title: 'Selecting Data',
title: () => t('Selecting Data'),
content: (...args: DomElementArg[]) => cssTooltipContent(
dom('div', 'Select the table containing the data to show.'),
dom('div', 'Use the 𝚺 icon to create summary (or pivot) tables, for totals or subtotals.'),
dom('div', t('Select the table containing the data to show.')),
dom('div', t('Use the 𝚺 icon to create summary (or pivot) tables, for totals or subtotals.')),
...args,
),
},
pageWidgetPickerSelectBy: {
title: 'Linking Widgets',
title: () => t('Linking Widgets'),
content: (...args: DomElementArg[]) => cssTooltipContent(
dom('div', 'Link your new widget to an existing widget on this page.'),
dom('div', `This is the secret to Grist's dynamic and productive layouts.`),
dom('div', cssLink({href: commonUrls.helpLinkingWidgets, target: '_blank'}, 'Learn more.')),
dom('div', t('Link your new widget to an existing widget on this page.')),
dom('div', t('This is the secret to Grist\'s dynamic and productive layouts.')),
dom('div', cssLink({href: commonUrls.helpLinkingWidgets, target: '_blank'}, t('Learn more.'))),
...args,
),
},
editCardLayout: {
title: 'Editing Card Layout',
title: () => t('Editing Card Layout'),
content: (...args: DomElementArg[]) => cssTooltipContent(
dom('div', 'Rearrange the fields in your card by dragging and resizing cells.'),
dom('div', 'Clicking ', cssIcon('EyeHide'),
' in each cell hides the field from this view without deleting it.'),
dom('div', t('Rearrange the fields in your card by dragging and resizing cells.')),
dom('div', t('Clicking {{EyeHideIcon}} in each cell hides the field from this view without deleting it.', {
EyeHideIcon: cssIcon('EyeHide')
})),
...args,
),
},
addNew: {
title: 'Add New',
title: () => t('Add New'),
content: (...args: DomElementArg[]) => cssTooltipContent(
dom('div', 'Click the Add New button to create new documents or workspaces, '
+ 'or import data.'),
dom('div', t('Click the Add New button to create new documents or workspaces, '
+ 'or import data.')),
...args,
),
},

View File

@ -117,7 +117,7 @@ function makeAnonIntro(homeModel: HomeModel) {
return [
css.docListHeader(t("Welcome to Grist!"), testId('welcome-title')),
cssIntroLine(t("Get started by exploring templates, or creating your first Grist document.")),
cssIntroLine(signUp, ' to save your work. ', // TODO i18n
cssIntroLine(t("{{signUp}} to save your work. ", {signUp}),
(shouldHideUiElement('helpCenter') ? null : t("Visit our {{link}} to learn more.", { link: helpCenterLink() })),
testId('welcome-text')),
makeCreateButtons(homeModel),

View File

@ -402,7 +402,8 @@
"Welcome to Grist, {{name}}!": "Welcome to Grist, {{name}}!",
"Welcome to {{orgName}}": "Welcome to {{orgName}}",
"You have read-only access to this site. Currently there are no documents.": "You have read-only access to this site. Currently there are no documents.",
"personal site": "personal site"
"personal site": "personal site",
"{{signUp}} to save your work. ": "{{signUp}} to save your work. "
},
"HomeLeftPane": {
"Access Details": "Access Details",
@ -899,5 +900,43 @@
},
"LanguageMenu": {
"Language": "Language"
},
"GristTooltips": {
"Apply conditional formatting to cells in this column when formula conditions are met.": "Apply conditional formatting to cells in this column when formula conditions are met.",
"Apply conditional formatting to rows based on formulas.": "Apply conditional formatting to rows based on formulas.",
"Cells in a reference column always identify an {{entire}} record in that table, but you may select which column from that record to show.": "Cells in a reference column always identify an {{entire}} record in that table, but you may select which column from that record to show.",
"Click on “Open row styles” to apply conditional formatting to rows.": "Click on “Open row styles” to apply conditional formatting to rows.",
"Click the Add New button to create new documents or workspaces, or import data.": "Click the Add New button to create new documents or workspaces, or import data.",
"Clicking {{EyeHideIcon}} in each cell hides the field from this view without deleting it.": "Clicking {{EyeHideIcon}} in each cell hides the field from this view without deleting it.",
"Editing Card Layout": "Editing Card Layout",
"Formulas that trigger in certain cases, and store the calculated value as data.": "Formulas that trigger in certain cases, and store the calculated value as data.",
"Learn more.": "Learn more.",
"Link your new widget to an existing widget on this page.": "Link your new widget to an existing widget on this page.",
"Linking Widgets": "Linking Widgets",
"Nested Filtering": "Nested Filtering",
"Only those rows will appear which match all of the filters.": "Only those rows will appear which match all of the filters.",
"Pinned filters are displayed as buttons above the widget.": "Pinned filters are displayed as buttons above the widget.",
"Pinning Filters": "Pinning Filters",
"Raw Data page": "Raw Data page",
"Rearrange the fields in your card by dragging and resizing cells.": "Rearrange the fields in your card by dragging and resizing cells.",
"Reference Columns": "Reference Columns",
"Reference columns are the key to {{relational}} data in Grist.": "Reference columns are the key to {{relational}} data in Grist.",
"Select the table containing the data to show.": "Select the table containing the data to show.",
"Select the table to link to.": "Select the table to link to.",
"Selecting Data": "Selecting Data",
"The Raw Data page lists all data tables in your document, including summary tables and tables not included in page layouts.": "The Raw Data page lists all data tables in your document, including summary tables and tables not included in page layouts.",
"The total size of all data in this document, excluding attachments.": "The total size of all data in this document, excluding attachments.",
"They allow for one record to point (or refer) to another.": "They allow for one record to point (or refer) to another.",
"This is the secret to Grist's dynamic and productive layouts.": "This is the secret to Grist's dynamic and productive layouts.",
"Try out changes in a copy, then decide whether to replace the original with your edits.": "Try out changes in a copy, then decide whether to replace the original with your edits.",
"Unpin to hide the the button while keeping the filter.": "Unpin to hide the the button while keeping the filter.",
"Updates every 5 minutes.": "Updates every 5 minutes.",
"Use the \\u{1D6BA} icon to create summary (or pivot) tables, for totals or subtotals.": "Use the \\u{1D6BA} icon to create summary (or pivot) tables, for totals or subtotals.",
"Useful for storing the timestamp or author of a new record, data cleaning, and more.": "Useful for storing the timestamp or author of a new record, data cleaning, and more.",
"You can filter by more than one column.": "You can filter by more than one column.",
"entire": "entire",
"relational": "relational",
"Access Rules": "Access Rules",
"Access rules give you the power to create nuanced rules to determine who can see or edit which parts of your document.": "Access rules give you the power to create nuanced rules to determine who can see or edit which parts of your document."
}
}