Make a good part of the app localizable and add French translations (#325)

Co-authored-by: Yohan Boniface <yohanboniface@free.fr>
This commit is contained in:
Arnaud Peich
2022-10-28 18:11:08 +02:00
committed by GitHub
parent ec20e7fb68
commit 79deeca640
78 changed files with 2364 additions and 665 deletions

View File

@@ -51,8 +51,11 @@ import {
Observable,
styled
} from 'grainjs';
import {makeT} from 'app/client/lib/localization';
import isEqual = require('lodash/isEqual');
const t = makeT('aclui.AccessRules');
// tslint:disable:max-classes-per-file no-console
// Types for the rows in the ACL tables we use.
@@ -317,21 +320,21 @@ export class AccessRules extends Disposable {
bigBasicButton({disabled: true}, dom.hide(this._savingEnabled),
dom.text((use) => {
const s = use(this._ruleStatus);
return s === RuleStatus.CheckPending ? 'Checking...' :
s === RuleStatus.Unchanged ? 'Saved' : 'Invalid';
return s === RuleStatus.CheckPending ? t('Checking') :
s === RuleStatus.Unchanged ? t('Saved') : t('Invalid');
}),
testId('rules-non-save')
),
bigPrimaryButton('Save', dom.show(this._savingEnabled),
bigPrimaryButton(t('Save'), dom.show(this._savingEnabled),
dom.on('click', () => this.save()),
testId('rules-save'),
),
bigBasicButton('Reset', dom.show(use => use(this._ruleStatus) !== RuleStatus.Unchanged),
bigBasicButton(t('Reset'), dom.show(use => use(this._ruleStatus) !== RuleStatus.Unchanged),
dom.on('click', () => this.update()),
testId('rules-revert'),
),
bigBasicButton('Add Table Rules', cssDropdownIcon('Dropdown'), {style: 'margin-left: auto'},
bigBasicButton(t('AddTableRules'), cssDropdownIcon('Dropdown'), {style: 'margin-left: auto'},
menu(() =>
this.allTableIds.map((tableId) =>
// Add the table on a timeout, to avoid disabling the clicked menu item
@@ -343,8 +346,8 @@ export class AccessRules extends Disposable {
),
),
),
bigBasicButton('Add User Attributes', dom.on('click', () => this._addUserAttributes())),
bigBasicButton('Users', cssDropdownIcon('Dropdown'), elem => this._aclUsersPopup.attachPopup(elem),
bigBasicButton(t('AddUserAttributes'), dom.on('click', () => this._addUserAttributes())),
bigBasicButton(t('Users'), cssDropdownIcon('Dropdown'), elem => this._aclUsersPopup.attachPopup(elem),
dom.style('visibility', use => use(this._aclUsersPopup.isInitialized) ? '' : 'hidden')),
),
cssConditionError({style: 'margin-left: 16px'},
@@ -354,15 +357,15 @@ export class AccessRules extends Disposable {
shadowScroll(
dom.maybe(use => use(this._userAttrRules).length, () =>
cssSection(
cssSectionHeading('User Attributes'),
cssSectionHeading(t('UserAttributes')),
cssTableRounded(
cssTableHeaderRow(
cssCell1(cssCell.cls('-rborder'), cssCell.cls('-center'), cssColHeaderCell('Name')),
cssCell4(
cssColumnGroup(
cssCell1(cssColHeaderCell('Attribute to Look Up')),
cssCell1(cssColHeaderCell('Lookup Table')),
cssCell1(cssColHeaderCell('Lookup Column')),
cssCell1(cssColHeaderCell(t('AttributeToLookUp'))),
cssCell1(cssColHeaderCell(t('LookupTable'))),
cssCell1(cssColHeaderCell(t('LookupColumn'))),
cssCellIcon(),
),
),
@@ -373,15 +376,15 @@ export class AccessRules extends Disposable {
),
dom.forEach(this._tableRules, (tableRules) => tableRules.buildDom()),
cssSection(
cssSectionHeading('Default Rules', testId('rule-table-header')),
cssSectionHeading(t("DefaultRules"), testId('rule-table-header')),
cssTableRounded(
cssTableHeaderRow(
cssCell1(cssCell.cls('-rborder'), cssCell.cls('-center'), cssColHeaderCell('Columns')),
cssCell4(
cssColumnGroup(
cssCellIcon(),
cssCell2(cssColHeaderCell('Condition')),
cssCell1(cssColHeaderCell('Permissions')),
cssCell2(cssColHeaderCell(t('Condition'))),
cssCell1(cssColHeaderCell(t('Permissions'))),
cssCellIcon(),
)
)
@@ -521,13 +524,13 @@ class TableRules extends Disposable {
public buildDom() {
return cssSection(
cssSectionHeading(
dom('span', 'Rules for table ', cssTableName(this._accessRules.getTableTitle(this.tableId))),
dom('span', t('RulesForTable'), cssTableName(this._accessRules.getTableTitle(this.tableId))),
cssIconButton(icon('Dots'), {style: 'margin-left: auto'},
menu(() => [
menuItemAsync(() => this._addColumnRuleSet(), 'Add Column Rule'),
menuItemAsync(() => this._addDefaultRuleSet(), 'Add Default Rule',
menuItemAsync(() => this._addColumnRuleSet(), t('AddColumnRule')),
menuItemAsync(() => this._addDefaultRuleSet(), t('AddDefaultRule'),
dom.cls('disabled', use => Boolean(use(this._defaultRuleSet)))),
menuItemAsync(() => this._accessRules.removeTableRules(this), 'Delete Table Rules'),
menuItemAsync(() => this._accessRules.removeTableRules(this), t('DeleteTableRules')),
]),
testId('rule-table-menu-btn'),
),
@@ -539,8 +542,8 @@ class TableRules extends Disposable {
cssCell4(
cssColumnGroup(
cssCellIcon(),
cssCell2(cssColHeaderCell('Condition')),
cssCell1(cssColHeaderCell('Permissions')),
cssCell2(cssColHeaderCell(t('Condition'))),
cssCell1(cssColHeaderCell(t('Permissions'))),
cssCellIcon(),
)
),
@@ -654,7 +657,7 @@ class TableRules extends Disposable {
class SpecialRules extends TableRules {
public buildDom() {
return cssSection(
cssSectionHeading('Special Rules', testId('rule-table-header')),
cssSectionHeading(t('SpecialRules'), testId('rule-table-header')),
this.buildColumnRuleSets(),
this.buildErrors(),
testId('rule-table'),
@@ -893,18 +896,17 @@ class DefaultObsRuleSet extends ObsRuleSet {
function getSpecialRuleDescription(type: string): string {
switch (type) {
case 'AccessRules':
return 'Allow everyone to view Access Rules.';
return t('AccessRulesDescription');
case 'FullCopies':
return 'Allow everyone to copy the entire document, or view it in full in fiddle mode.\n' +
'Useful for examples and templates, but not for sensitive data.';
return t('FullCopiesDescription');
default: return type;
}
}
function getSpecialRuleName(type: string): string {
switch (type) {
case 'AccessRules': return 'Permission to view Access Rules';
case 'FullCopies': return 'Permission to access the document in full when needed';
case 'AccessRules': return t('AccessRulesName');
case 'FullCopies': return t('FullCopies');
default: return type;
}
}
@@ -1037,7 +1039,7 @@ class ObsUserAttributeRule extends Disposable {
cssCell1(cssCell.cls('-rborder'),
cssCellContent(
cssInput(this._name, async (val) => this._name.set(val),
{placeholder: 'Attribute name'},
{placeholder: t('AttributeNamePlaceholder')},
(this._options.focus ? (elem) => { setTimeout(() => elem.focus(), 0); } : null),
testId('rule-userattr-name'),
),
@@ -1253,9 +1255,9 @@ class ObsRulePart extends Disposable {
setValue: (value) => this._setAclFormula(value),
placeholder: dom.text((use) => {
return (
this._ruleSet.isSoleCondition(use, this) ? 'Everyone' :
this._ruleSet.isLastCondition(use, this) ? 'Everyone Else' :
'Enter Condition'
this._ruleSet.isSoleCondition(use, this) ? t('Everyone') :
this._ruleSet.isLastCondition(use, this) ? t('EveryoneElse') :
t('EnterCondition')
);
}),
getSuggestions: (prefix) => this._completions.get(),

View File

@@ -10,10 +10,13 @@ import {ALL_PERMISSION_PROPS, emptyPermissionSet} from 'app/common/ACLPermission
import {capitalize} from 'app/common/gutil';
import {dom, DomElementArg, Observable, styled} from 'grainjs';
import isEqual = require('lodash/isEqual');
import {makeT} from 'app/client/lib/localization';
// One of the strings 'read', 'update', etc.
export type PermissionKey = keyof PartialPermissionSet;
const t = makeT('aclui.PermissionsWidget');
/**
* Renders a box for each of availableBits, and a dropdown with a description and some shortcuts.
*/
@@ -61,13 +64,13 @@ export function permissionsWidget(
null
),
// If the set matches any recognized pattern, mark that item with a tick (checkmark).
cssMenuItem(() => setPermissions(allowAll), tick(isEqual(pset.get(), allowAll)), 'Allow All',
cssMenuItem(() => setPermissions(allowAll), tick(isEqual(pset.get(), allowAll)), t('AllowAll'),
dom.cls('disabled', options.disabled)
),
cssMenuItem(() => setPermissions(denyAll), tick(isEqual(pset.get(), denyAll)), 'Deny All',
cssMenuItem(() => setPermissions(denyAll), tick(isEqual(pset.get(), denyAll)), t('DenyAll'),
dom.cls('disabled', options.disabled)
),
cssMenuItem(() => setPermissions(readOnly), tick(isEqual(pset.get(), readOnly)), 'Read Only',
cssMenuItem(() => setPermissions(readOnly), tick(isEqual(pset.get(), readOnly)), t('ReadOnly'),
dom.cls('disabled', options.disabled)
),
cssMenuItem(() => setPermissions(empty),