mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-01-23 02:36:05 +00:00
Merge pull request #6033 from steindvart/settings-tabs
Organize settings page into horizontal tabs for improved usability
This commit is contained in:
commit
8580742272
29 changed files with 241 additions and 136 deletions
|
|
@ -24,18 +24,28 @@ const filterGlobalConfigForm = (cfg: ConfigFormSection<any>): boolean => {
|
|||
);
|
||||
};
|
||||
|
||||
export const GLOBAL_CONFIG_FORM_CONFIG: ConfigFormConfig = [
|
||||
// Tab: General - Language, App Features, Misc, Short Syntax, Sound (specified separately in html)
|
||||
export const GLOBAL_GENERAL_FORM_CONFIG: ConfigFormConfig = [
|
||||
LANGUAGE_SELECTION_FORM_FORM,
|
||||
APP_FEATURES_FORM_CFG,
|
||||
MISC_SETTINGS_FORM_CFG,
|
||||
SHORT_SYNTAX_FORM_CFG,
|
||||
IDLE_FORM_CFG,
|
||||
KEYBOARD_SETTINGS_FORM_CFG,
|
||||
TIME_TRACKING_FORM_CFG,
|
||||
REMINDER_FORM_CFG,
|
||||
SCHEDULE_FORM_CFG,
|
||||
].filter(filterGlobalConfigForm);
|
||||
|
||||
// Tab: Time & Tracking - Time Tracking, Idle, Schedule, Reminder
|
||||
export const GLOBAL_TIME_TRACKING_FORM_CONFIG: ConfigFormConfig = [
|
||||
TIME_TRACKING_FORM_CFG,
|
||||
IDLE_FORM_CFG,
|
||||
SCHEDULE_FORM_CFG,
|
||||
REMINDER_FORM_CFG,
|
||||
].filter(filterGlobalConfigForm);
|
||||
|
||||
// Tab: Plugins
|
||||
export const GLOBAL_PLUGINS_FORM_CONFIG: ConfigFormConfig = [].filter(
|
||||
filterGlobalConfigForm,
|
||||
);
|
||||
|
||||
export const GLOBAL_IMEX_FORM_CONFIG: ConfigFormConfig = [
|
||||
// NOTE: the backup form is added dynamically due to async prop required
|
||||
IMEX_FORM,
|
||||
|
|
|
|||
|
|
@ -1,90 +1,132 @@
|
|||
<div class="page-settings page-wrapper">
|
||||
@if (globalCfg) {
|
||||
<div>
|
||||
<div class="section-wrapper component-wrapper">
|
||||
<h1 class="mat-h1">{{ T.PS.GLOBAL_SETTINGS | translate }}</h1>
|
||||
<theme-selector></theme-selector>
|
||||
@for (section of globalConfigFormCfg; track section.key) {
|
||||
<section class="config-section section-{{ section.key }}">
|
||||
<config-section
|
||||
(save)="saveGlobalCfg($event)"
|
||||
[cfg]="getGlobalCfgSection(section.key)"
|
||||
[section]="section"
|
||||
></config-section>
|
||||
</section>
|
||||
}
|
||||
<section class="config-section">
|
||||
<config-sound-form
|
||||
[cfg]="getGlobalCfgSection('sound')"
|
||||
(save)="saveGlobalCfg($event)"
|
||||
></config-sound-form>
|
||||
</section>
|
||||
<div class="settings-container">
|
||||
<h1 class="mat-h1 settings-title">{{ T.PS.GLOBAL_SETTINGS | translate }}</h1>
|
||||
|
||||
<div>
|
||||
<h2
|
||||
class="mat-h2"
|
||||
style="margin-top: 32px"
|
||||
>
|
||||
{{ T.PS.PLUGINS | translate }}
|
||||
</h2>
|
||||
<section class="config-section plugin-section">
|
||||
<collapsible
|
||||
[isIconBefore]="true"
|
||||
[isExpanded]="false"
|
||||
[title]="T.PS.PLUGINS | translate"
|
||||
>
|
||||
<plugin-management></plugin-management>
|
||||
</collapsible>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="tour-productivityHelper">
|
||||
<h2
|
||||
class="mat-h2"
|
||||
style="margin-top: 32px"
|
||||
>
|
||||
{{ T.PS.PRODUCTIVITY_HELPER | translate }}
|
||||
</h2>
|
||||
@for (section of globalProductivityConfigFormCfg; track section.key) {
|
||||
<mat-tab-group
|
||||
class="settings-tabs"
|
||||
[(selectedIndex)]="selectedTabIndex"
|
||||
animationDuration="200ms"
|
||||
>
|
||||
<!-- Tab: General -->
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<mat-icon class="tab-icon">settings</mat-icon>
|
||||
<span class="tab-label">{{ 'PS.TABS.GENERAL' | translate }}</span>
|
||||
</ng-template>
|
||||
<div class="tab-content">
|
||||
<theme-selector></theme-selector>
|
||||
@for (section of generalFormCfg; track section.key) {
|
||||
<section class="config-section section-{{ section.key }}">
|
||||
<config-section
|
||||
(save)="saveGlobalCfg($event)"
|
||||
[cfg]="getGlobalCfgSection(section.key)"
|
||||
[section]="section"
|
||||
></config-section>
|
||||
</section>
|
||||
}
|
||||
<!-- @todo: Create a single style for forming all the settings elements.
|
||||
Make all as "sections" or as "forms" consistently.
|
||||
-->
|
||||
<section class="config-section">
|
||||
<config-section
|
||||
<config-sound-form
|
||||
[cfg]="getGlobalCfgSection('sound')"
|
||||
(save)="saveGlobalCfg($event)"
|
||||
[cfg]="getGlobalCfgSection(section.key)"
|
||||
[section]="section"
|
||||
></config-section>
|
||||
></config-sound-form>
|
||||
</section>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
<h2
|
||||
class="mat-h2"
|
||||
style="margin-top: 32px"
|
||||
>
|
||||
{{ T.PS.SYNC_EXPORT | translate }}
|
||||
</h2>
|
||||
<!-- Tab: Time & Tracking -->
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<mat-icon class="tab-icon">timer</mat-icon>
|
||||
<span class="tab-label">{{ 'PS.TABS.TIME_TRACKING' | translate }}</span>
|
||||
</ng-template>
|
||||
<div class="tab-content">
|
||||
@for (section of timeTrackingFormCfg; track section.key) {
|
||||
<section class="config-section section-{{ section.key }}">
|
||||
<config-section
|
||||
(save)="saveGlobalCfg($event)"
|
||||
[cfg]="getGlobalCfgSection(section.key)"
|
||||
[section]="section"
|
||||
></config-section>
|
||||
</section>
|
||||
}
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
<section class="config-section tour-syncSection">
|
||||
<!-- NOTE: we need to debounce, as external updates end us in an endless loop -->
|
||||
@let syncSettingsForm = syncSettingsService.syncSettingsForm$ | async;
|
||||
@if (syncSettingsForm) {
|
||||
<config-section
|
||||
(save)="syncSettingsService.updateSettingsFromForm($event.config)"
|
||||
[cfg]="syncSettingsForm"
|
||||
[section]="globalSyncConfigFormCfg"
|
||||
></config-section>
|
||||
}
|
||||
</section>
|
||||
<!-- Tab: Productivity -->
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<mat-icon class="tab-icon">trending_up</mat-icon>
|
||||
<span class="tab-label">{{ 'PS.TABS.PRODUCTIVITY' | translate }}</span>
|
||||
</ng-template>
|
||||
<div class="tab-content tour-productivityHelper">
|
||||
@for (section of globalProductivityConfigFormCfg; track section.key) {
|
||||
<section class="config-section">
|
||||
<config-section
|
||||
(save)="saveGlobalCfg($event)"
|
||||
[cfg]="getGlobalCfgSection(section.key)"
|
||||
[section]="section"
|
||||
></config-section>
|
||||
</section>
|
||||
}
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
@for (section of globalImexFormCfg; track section.key) {
|
||||
<section class="config-section imex-section">
|
||||
<config-section
|
||||
(save)="saveGlobalCfg($event)"
|
||||
[cfg]="getGlobalCfgSection(section.key)"
|
||||
[section]="section"
|
||||
></config-section>
|
||||
</section>
|
||||
}
|
||||
</div>
|
||||
<!-- Tab: Plugins -->
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<mat-icon class="tab-icon">extension</mat-icon>
|
||||
<span class="tab-label">{{ 'PS.TABS.PLUGINS' | translate }}</span>
|
||||
</ng-template>
|
||||
<div class="tab-content">
|
||||
<section class="config-section plugin-section">
|
||||
<plugin-management></plugin-management>
|
||||
</section>
|
||||
@for (section of pluginsShortcutsFormCfg; track section.key) {
|
||||
<section class="config-section section-{{ section.key }}">
|
||||
<config-section
|
||||
(save)="saveGlobalCfg($event)"
|
||||
[cfg]="getGlobalCfgSection(section.key)"
|
||||
[section]="section"
|
||||
></config-section>
|
||||
</section>
|
||||
}
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
<!-- Tab: Sync & Backup -->
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<mat-icon class="tab-icon">cloud_sync</mat-icon>
|
||||
<span class="tab-label">{{ 'PS.TABS.SYNC_BACKUP' | translate }}</span>
|
||||
</ng-template>
|
||||
<div class="tab-content">
|
||||
<section class="config-section tour-syncSection">
|
||||
@let syncSettingsForm = syncSettingsService.syncSettingsForm$ | async;
|
||||
@if (syncSettingsForm) {
|
||||
<config-section
|
||||
(save)="syncSettingsService.updateSettingsFromForm($event.config)"
|
||||
[cfg]="syncSettingsForm"
|
||||
[section]="globalSyncConfigFormCfg"
|
||||
></config-section>
|
||||
}
|
||||
</section>
|
||||
|
||||
@for (section of globalImexFormCfg; track section.key) {
|
||||
<section class="config-section imex-section">
|
||||
<config-section
|
||||
(save)="saveGlobalCfg($event)"
|
||||
[cfg]="getGlobalCfgSection(section.key)"
|
||||
[section]="section"
|
||||
></config-section>
|
||||
</section>
|
||||
}
|
||||
</div>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,14 +3,59 @@
|
|||
.page-settings {
|
||||
text-align: start;
|
||||
|
||||
collapsible {
|
||||
position: relative;
|
||||
.settings-container {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.section-wrapper {
|
||||
//display: grid;
|
||||
//grid-template-columns: 50% 50%;
|
||||
//grid-gap: 0 var(--s2);
|
||||
.settings-title {
|
||||
margin-bottom: var(--s2);
|
||||
}
|
||||
|
||||
.settings-tabs {
|
||||
::ng-deep .mat-mdc-tab-header {
|
||||
border-bottom: 1px solid var(--divider-color);
|
||||
margin-bottom: var(--s2);
|
||||
}
|
||||
|
||||
::ng-deep .mat-mdc-tab {
|
||||
min-width: 120px;
|
||||
|
||||
@include mq(xs, max) {
|
||||
min-width: 90px;
|
||||
padding: 0 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-icon {
|
||||
margin-inline-end: 8px;
|
||||
font-size: 20px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
|
||||
@include mq(xs, max) {
|
||||
margin-inline-end: 4px;
|
||||
font-size: 18px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-label {
|
||||
@include mq(xs, max) {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
padding-top: var(--s2);
|
||||
max-width: 900px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
collapsible {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.config-section {
|
||||
|
|
@ -21,7 +66,6 @@
|
|||
background: var(--card-bg);
|
||||
|
||||
background-color: var(--card-bg);
|
||||
//background-color: var(--bg-slightly-lighter);
|
||||
|
||||
.md-title {
|
||||
margin-top: 0;
|
||||
|
|
@ -70,15 +114,9 @@
|
|||
}
|
||||
|
||||
.collapsible-panel {
|
||||
//border-top: 1px solid black;
|
||||
overflow: visible;
|
||||
|
||||
> * {
|
||||
// for help icon positioning
|
||||
// does not work because of translate on the slide down ani element
|
||||
// position: static;
|
||||
|
||||
// add a padding
|
||||
padding: 0 $this-panel-padding-left-right;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,9 +9,11 @@ import {
|
|||
} from '@angular/core';
|
||||
import { GlobalConfigService } from '../../features/config/global-config.service';
|
||||
import {
|
||||
GLOBAL_CONFIG_FORM_CONFIG,
|
||||
GLOBAL_GENERAL_FORM_CONFIG,
|
||||
GLOBAL_IMEX_FORM_CONFIG,
|
||||
GLOBAL_PLUGINS_FORM_CONFIG,
|
||||
GLOBAL_PRODUCTIVITY_FORM_CONFIG,
|
||||
GLOBAL_TIME_TRACKING_FORM_CONFIG,
|
||||
} from '../../features/config/global-config-form-config.const';
|
||||
import {
|
||||
ConfigFormConfig,
|
||||
|
|
@ -49,12 +51,13 @@ import { SyncWrapperService } from '../../imex/sync/sync-wrapper.service';
|
|||
import { UserProfileService } from '../../features/user-profile/user-profile.service';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { DialogDisableProfilesConfirmationComponent } from '../../features/user-profile/dialog-disable-profiles-confirmation/dialog-disable-profiles-confirmation.component';
|
||||
import { SuperSyncRestoreService } from '../../imex/sync/super-sync-restore.service';
|
||||
import { DialogRestorePointComponent } from '../../imex/sync/dialog-restore-point/dialog-restore-point.component';
|
||||
import { LegacySyncProvider } from '../../imex/sync/legacy-sync-provider.model';
|
||||
import { DialogChangeEncryptionPasswordComponent } from '../../imex/sync/dialog-change-encryption-password/dialog-change-encryption-password.component';
|
||||
import { DialogConfirmComponent } from '../../ui/dialog-confirm/dialog-confirm.component';
|
||||
import { LS } from '../../core/persistence/storage-keys.const';
|
||||
import { MatTab, MatTabGroup, MatTabLabel } from '@angular/material/tabs';
|
||||
import { MatIcon } from '@angular/material/icon';
|
||||
|
||||
@Component({
|
||||
selector: 'config-page',
|
||||
|
|
@ -69,22 +72,33 @@ import { LS } from '../../core/persistence/storage-keys.const';
|
|||
AsyncPipe,
|
||||
PluginManagementComponent,
|
||||
CollapsibleComponent,
|
||||
MatTabGroup,
|
||||
MatTab,
|
||||
MatTabLabel,
|
||||
MatIcon,
|
||||
],
|
||||
})
|
||||
export class ConfigPageComponent implements OnInit, OnDestroy {
|
||||
private readonly _cd = inject(ChangeDetectorRef);
|
||||
private readonly _providerManager = inject(SyncProviderManager);
|
||||
readonly configService = inject(GlobalConfigService);
|
||||
readonly syncSettingsService = inject(SyncConfigService);
|
||||
private readonly _syncWrapperService = inject(SyncWrapperService);
|
||||
private readonly _pluginBridgeService = inject(PluginBridgeService);
|
||||
private readonly _snackService = inject(SnackService);
|
||||
private readonly _userProfileService = inject(UserProfileService);
|
||||
private readonly _matDialog = inject(MatDialog);
|
||||
private readonly _superSyncRestoreService = inject(SuperSyncRestoreService);
|
||||
|
||||
readonly configService = inject(GlobalConfigService);
|
||||
readonly syncSettingsService = inject(SyncConfigService);
|
||||
|
||||
T: typeof T = T;
|
||||
globalConfigFormCfg: ConfigFormConfig;
|
||||
|
||||
selectedTabIndex = 0;
|
||||
|
||||
// @todo - find better names for tabs configs forms
|
||||
// Tab-specific form configurations
|
||||
generalFormCfg: ConfigFormConfig;
|
||||
timeTrackingFormCfg: ConfigFormConfig;
|
||||
pluginsShortcutsFormCfg: ConfigFormConfig;
|
||||
globalImexFormCfg: ConfigFormConfig;
|
||||
globalProductivityConfigFormCfg: ConfigFormConfig;
|
||||
globalSyncConfigFormCfg = this._buildSyncFormConfig();
|
||||
|
|
@ -114,8 +128,10 @@ export class ConfigPageComponent implements OnInit, OnDestroy {
|
|||
private _subs: Subscription = new Subscription();
|
||||
|
||||
constructor() {
|
||||
// somehow they are only unproblematic if assigned here
|
||||
this.globalConfigFormCfg = GLOBAL_CONFIG_FORM_CONFIG.slice();
|
||||
// Initialize tab-specific form configurations
|
||||
this.generalFormCfg = GLOBAL_GENERAL_FORM_CONFIG.slice();
|
||||
this.timeTrackingFormCfg = GLOBAL_TIME_TRACKING_FORM_CONFIG.slice();
|
||||
this.pluginsShortcutsFormCfg = GLOBAL_PLUGINS_FORM_CONFIG.slice();
|
||||
this.globalImexFormCfg = GLOBAL_IMEX_FORM_CONFIG.slice();
|
||||
this.globalProductivityConfigFormCfg = GLOBAL_PRODUCTIVITY_FORM_CONFIG.slice();
|
||||
|
||||
|
|
@ -150,8 +166,9 @@ export class ConfigPageComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
private _updateKeyboardFormWithPluginShortcuts(shortcuts: PluginShortcutCfg[]): void {
|
||||
// Find keyboard form section
|
||||
const keyboardFormIndex = this.globalConfigFormCfg.findIndex(
|
||||
// @todo - make separate core shortcuts and plugins shortcuts settings
|
||||
// Find keyboard form section in general tab configuration
|
||||
const keyboardFormIndex = this.generalFormCfg.findIndex(
|
||||
(section) => section.key === 'keyboard',
|
||||
);
|
||||
|
||||
|
|
@ -160,7 +177,7 @@ export class ConfigPageComponent implements OnInit, OnDestroy {
|
|||
return;
|
||||
}
|
||||
|
||||
const keyboardSection = this.globalConfigFormCfg[keyboardFormIndex];
|
||||
const keyboardSection = this.generalFormCfg[keyboardFormIndex];
|
||||
|
||||
// Remove existing plugin shortcuts and header from the form
|
||||
const filteredItems = (keyboardSection.items || []).filter((item) => {
|
||||
|
|
@ -196,10 +213,10 @@ export class ConfigPageComponent implements OnInit, OnDestroy {
|
|||
};
|
||||
|
||||
// Create a new config array to ensure Angular detects the change
|
||||
this.globalConfigFormCfg = [
|
||||
...this.globalConfigFormCfg.slice(0, keyboardFormIndex),
|
||||
this.generalFormCfg = [
|
||||
...this.generalFormCfg.slice(0, keyboardFormIndex),
|
||||
newKeyboardSection,
|
||||
...this.globalConfigFormCfg.slice(keyboardFormIndex + 1),
|
||||
...this.generalFormCfg.slice(keyboardFormIndex + 1),
|
||||
];
|
||||
|
||||
// Trigger change detection
|
||||
|
|
|
|||
|
|
@ -2196,11 +2196,17 @@ const T = {
|
|||
NO_PLUGINS_INSTALLED: 'PS.NO_PLUGINS_INSTALLED',
|
||||
PLUGINS: 'PS.PLUGINS',
|
||||
PRIVACY_POLICY: 'PS.PRIVACY_POLICY',
|
||||
PRODUCTIVITY_HELPER: 'PS.PRODUCTIVITY_HELPER',
|
||||
PROJECT_SETTINGS: 'PS.PROJECT_SETTINGS',
|
||||
PROVIDE_FEEDBACK: 'PS.PROVIDE_FEEDBACK',
|
||||
RELOAD: 'PS.RELOAD',
|
||||
SYNC_EXPORT: 'PS.SYNC_EXPORT',
|
||||
TABS: {
|
||||
GENERAL: 'PS.TABS.GENERAL',
|
||||
TIME_TRACKING: 'PS.TABS.TIME_TRACKING',
|
||||
PRODUCTIVITY: 'PS.TABS.PRODUCTIVITY',
|
||||
PLUGINS: 'PS.TABS.PLUGINS',
|
||||
SYNC_BACKUP: 'PS.TABS.SYNC_BACKUP',
|
||||
},
|
||||
TAG_SETTINGS: 'PS.TAG_SETTINGS',
|
||||
TOGGLE_DARK_MODE: 'PS.TOGGLE_DARK_MODE',
|
||||
UPDATE_APP: 'PS.UPDATE_APP',
|
||||
|
|
|
|||
|
|
@ -1895,7 +1895,6 @@
|
|||
"NO_PLUGINS_INSTALLED": "لا توجد إضافات مثبتة حاليا",
|
||||
"PLUGINS": "الإضافات",
|
||||
"PRIVACY_POLICY": "سياسة الخصوصية",
|
||||
"PRODUCTIVITY_HELPER": "مساعد الإنتاجية",
|
||||
"PROJECT_SETTINGS": "إعدادات محددة للمشروع",
|
||||
"PROVIDE_FEEDBACK": "تقديم التغذية الراجعة",
|
||||
"SYNC_EXPORT": "المزامنة والتصدير",
|
||||
|
|
|
|||
|
|
@ -1132,7 +1132,6 @@
|
|||
"PS": {
|
||||
"GLOBAL_SETTINGS": "Celková nastavení",
|
||||
"PRIVACY_POLICY": "Zásady ochrany osobních údajů",
|
||||
"PRODUCTIVITY_HELPER": "Pomocník produktivity",
|
||||
"PROJECT_SETTINGS": "Nastavení specifické pro projekt",
|
||||
"PROVIDE_FEEDBACK": "Poskytnout zpětnou vazbu",
|
||||
"SYNC_EXPORT": "Synchronizace a export",
|
||||
|
|
|
|||
|
|
@ -1975,7 +1975,6 @@
|
|||
"NO_PLUGINS_INSTALLED": "Derzeit sind keine Plugins installiert",
|
||||
"PLUGINS": "Plugins",
|
||||
"PRIVACY_POLICY": "Datenschutzerklärung",
|
||||
"PRODUCTIVITY_HELPER": "Produktivitäts-Helfer",
|
||||
"PROJECT_SETTINGS": "Projektspezifische Einstellungen",
|
||||
"PROVIDE_FEEDBACK": "Rückmeldung geben",
|
||||
"SYNC_EXPORT": "Synchronisieren und exportieren",
|
||||
|
|
|
|||
|
|
@ -2181,11 +2181,17 @@
|
|||
"NO_PLUGINS_INSTALLED": "No plugins are currently installed",
|
||||
"PLUGINS": "Plugins",
|
||||
"PRIVACY_POLICY": "Privacy Policy",
|
||||
"PRODUCTIVITY_HELPER": "Productivity Helper",
|
||||
"PROJECT_SETTINGS": "Project Specific Settings",
|
||||
"PROVIDE_FEEDBACK": "Provide Feedback",
|
||||
"RELOAD": "Reload",
|
||||
"SYNC_EXPORT": "Sync & Export",
|
||||
"TABS": {
|
||||
"GENERAL": "General",
|
||||
"TIME_TRACKING": "Time & Tracking",
|
||||
"PRODUCTIVITY": "Productivity",
|
||||
"PLUGINS": "Plugins",
|
||||
"SYNC_BACKUP": "Sync & Backup"
|
||||
},
|
||||
"TAG_SETTINGS": "Tag Specific Settings",
|
||||
"TOGGLE_DARK_MODE": "Toggle Dark Mode",
|
||||
"UPDATE_APP": "Update App"
|
||||
|
|
|
|||
|
|
@ -1975,7 +1975,6 @@
|
|||
"NO_PLUGINS_INSTALLED": "No hay plugins instalados actualmente",
|
||||
"PLUGINS": "Plugins",
|
||||
"PRIVACY_POLICY": "Política de Privacidad",
|
||||
"PRODUCTIVITY_HELPER": "Ayudante de Productividad",
|
||||
"PROJECT_SETTINGS": "Ajustes Específicos del Proyecto",
|
||||
"PROVIDE_FEEDBACK": "Proporcionar Feedback",
|
||||
"SYNC_EXPORT": "Sincronizar y Exportar",
|
||||
|
|
|
|||
|
|
@ -1895,7 +1895,6 @@
|
|||
"NO_PLUGINS_INSTALLED": "در حال حاضر هیچ پلاگینی نصب نشده است",
|
||||
"PLUGINS": "پلاگین",
|
||||
"PRIVACY_POLICY": "Privacy Policy",
|
||||
"PRODUCTIVITY_HELPER": "Productivity Helper",
|
||||
"PROJECT_SETTINGS": "Project Specific Settings",
|
||||
"PROVIDE_FEEDBACK": "ارائه بازخورد",
|
||||
"SYNC_EXPORT": "همگام سازی و صادرات",
|
||||
|
|
|
|||
|
|
@ -1977,7 +1977,6 @@
|
|||
"NO_PLUGINS_INSTALLED": "Laajennuksia ei ole asennettuna tällä hetkellä",
|
||||
"PLUGINS": "Laajennukset",
|
||||
"PRIVACY_POLICY": "Tietosuojakäytäntö",
|
||||
"PRODUCTIVITY_HELPER": "Tuottavuusavustaja",
|
||||
"PROJECT_SETTINGS": "Projektikohtaiset asetukset",
|
||||
"PROVIDE_FEEDBACK": "Anna palautetta",
|
||||
"SYNC_EXPORT": "Synkronointi & Vienti",
|
||||
|
|
|
|||
|
|
@ -1977,7 +1977,6 @@
|
|||
"NO_PLUGINS_INSTALLED": "Aucun plugin n'est actuellement installé",
|
||||
"PLUGINS": "Plugins",
|
||||
"PRIVACY_POLICY": "Politique privée",
|
||||
"PRODUCTIVITY_HELPER": "Aide à la productivité",
|
||||
"PROJECT_SETTINGS": "Paramètres spécifiques au projet",
|
||||
"PROVIDE_FEEDBACK": "Fournir une réponse",
|
||||
"SYNC_EXPORT": "Synchroniser et exporter",
|
||||
|
|
|
|||
|
|
@ -1526,7 +1526,6 @@
|
|||
"PS": {
|
||||
"GLOBAL_SETTINGS": "Globalne postavke",
|
||||
"PRIVACY_POLICY": "Politika privatnosti",
|
||||
"PRODUCTIVITY_HELPER": "Pomoćnik produktivnosti",
|
||||
"PROJECT_SETTINGS": "Postavke određenog projekta",
|
||||
"PROVIDE_FEEDBACK": "Pošalji povratne informacije",
|
||||
"SYNC_EXPORT": "Sinkronizacija i izvoz",
|
||||
|
|
|
|||
|
|
@ -1977,7 +1977,6 @@
|
|||
"NO_PLUGINS_INSTALLED": "Tidak ada plugin yang terpasang saat ini",
|
||||
"PLUGINS": "Plugin",
|
||||
"PRIVACY_POLICY": "Kebijakan pribadi",
|
||||
"PRODUCTIVITY_HELPER": "Pembantu Produktivitas",
|
||||
"PROJECT_SETTINGS": "Pengaturan Khusus Proyek",
|
||||
"PROVIDE_FEEDBACK": "Berikan umpan balik",
|
||||
"SYNC_EXPORT": "Sinkron & Ekspor",
|
||||
|
|
|
|||
|
|
@ -1977,7 +1977,6 @@
|
|||
"NO_PLUGINS_INSTALLED": "Nessun plugin attualmente installato",
|
||||
"PLUGINS": "Plugin",
|
||||
"PRIVACY_POLICY": "Politica sulla Privacy",
|
||||
"PRODUCTIVITY_HELPER": "Aiuto produttività",
|
||||
"PROJECT_SETTINGS": "Impostazioni specifiche del progetto",
|
||||
"PROVIDE_FEEDBACK": "La tua opinione",
|
||||
"SYNC_EXPORT": "Sincronizza ed esporta",
|
||||
|
|
|
|||
|
|
@ -1886,7 +1886,6 @@
|
|||
"PS": {
|
||||
"GLOBAL_SETTINGS": "全体設定",
|
||||
"PRIVACY_POLICY": "プライベートポリシー",
|
||||
"PRODUCTIVITY_HELPER": "生産性ヘルパー",
|
||||
"PROJECT_SETTINGS": "プロジェクト固有の設定",
|
||||
"PROVIDE_FEEDBACK": "フィードバックを提供します",
|
||||
"SYNC_EXPORT": "同期とエクスポート",
|
||||
|
|
|
|||
|
|
@ -1554,7 +1554,6 @@
|
|||
"PS": {
|
||||
"GLOBAL_SETTINGS": "전체 설정",
|
||||
"PRIVACY_POLICY": "개인 정책",
|
||||
"PRODUCTIVITY_HELPER": "생산성 도우미",
|
||||
"PROJECT_SETTINGS": "프로젝트 별 설정",
|
||||
"PROVIDE_FEEDBACK": "피드백을 제공하다",
|
||||
"SYNC_EXPORT": "동기화 및 내보내기",
|
||||
|
|
|
|||
|
|
@ -1977,7 +1977,6 @@
|
|||
"NO_PLUGINS_INSTALLED": "Ingen plugins er installert for øyeblikket",
|
||||
"PLUGINS": "Plugins",
|
||||
"PRIVACY_POLICY": "Privat policy",
|
||||
"PRODUCTIVITY_HELPER": "Produktivitetshjelper",
|
||||
"PROJECT_SETTINGS": "Prosjektspesifikke innstillinger",
|
||||
"PROVIDE_FEEDBACK": "Gi tilbakemelding",
|
||||
"SYNC_EXPORT": "Synkroniser og eksporter",
|
||||
|
|
|
|||
|
|
@ -1977,7 +1977,6 @@
|
|||
"NO_PLUGINS_INSTALLED": "Er zijn momenteel geen plugins geïnstalleerd",
|
||||
"PLUGINS": "Plugins",
|
||||
"PRIVACY_POLICY": "Privébeleid",
|
||||
"PRODUCTIVITY_HELPER": "Productiviteitshulp",
|
||||
"PROJECT_SETTINGS": "Projectspecifieke instellingen",
|
||||
"PROVIDE_FEEDBACK": "Geef feedback",
|
||||
"SYNC_EXPORT": "Synchroniseren en exporteren",
|
||||
|
|
|
|||
|
|
@ -2024,7 +2024,6 @@
|
|||
"NO_PLUGINS_INSTALLED": "Obecnie nie ma zainstalowanych wtyczek",
|
||||
"PLUGINS": "Wtyczki",
|
||||
"PRIVACY_POLICY": "Polityka Prywatności",
|
||||
"PRODUCTIVITY_HELPER": "Pomocnik Produktywności",
|
||||
"PROJECT_SETTINGS": "Ustawienia dla Projektu",
|
||||
"PROVIDE_FEEDBACK": "Prześlij Opinię",
|
||||
"SYNC_EXPORT": "Synchronizacja i Eksport",
|
||||
|
|
|
|||
|
|
@ -1977,7 +1977,6 @@
|
|||
"NO_PLUGINS_INSTALLED": "Nenhum plugin está instalado no momento",
|
||||
"PLUGINS": "Plugins",
|
||||
"PRIVACY_POLICY": "Política de Privacidade",
|
||||
"PRODUCTIVITY_HELPER": "Auxiliar de produtividade",
|
||||
"PROJECT_SETTINGS": "Configurações específicas do projeto",
|
||||
"PROVIDE_FEEDBACK": "Fornecer feedback",
|
||||
"SYNC_EXPORT": "Sincronizar e Exportar",
|
||||
|
|
|
|||
|
|
@ -1977,7 +1977,6 @@
|
|||
"NO_PLUGINS_INSTALLED": "Nenhum plugin está atualmente instalado",
|
||||
"PLUGINS": "Plugins",
|
||||
"PRIVACY_POLICY": "Política Privada",
|
||||
"PRODUCTIVITY_HELPER": "Auxiliar de produtividade",
|
||||
"PROJECT_SETTINGS": "Configurações específicas do projeto",
|
||||
"PROVIDE_FEEDBACK": "Dar uma resposta",
|
||||
"SYNC_EXPORT": "Sincronizar e exportar",
|
||||
|
|
|
|||
|
|
@ -1979,11 +1979,19 @@
|
|||
"NO_PLUGINS_INSTALLED": "Нет установленных плагинов",
|
||||
"PLUGINS": "Плагины",
|
||||
"PRIVACY_POLICY": "Политика конфиденциальности",
|
||||
"PRODUCTIVITY_HELPER": "Помощник производительности",
|
||||
"PROJECT_SETTINGS": "Настройки проекта",
|
||||
"PROVIDE_FEEDBACK": "Обратная связь",
|
||||
"SYNC_EXPORT": "Синхронизация и экспорт",
|
||||
"TAG_SETTINGS": "Специальные настройки тегов"
|
||||
"TABS": {
|
||||
"GENERAL": "Общие",
|
||||
"TIME_TRACKING": "Время и отслеживание",
|
||||
"PRODUCTIVITY": "Продуктивность",
|
||||
"PLUGINS": "Плагины",
|
||||
"SYNC_BACKUP": "Синхронизация и резервирование"
|
||||
},
|
||||
"TAG_SETTINGS": "Специальные настройки тега",
|
||||
"TOGGLE_DARK_MODE": "Переключить темный режим",
|
||||
"UPDATE_APP": "Обновить приложение"
|
||||
},
|
||||
"SCHEDULE": {
|
||||
"LAST": "Прошедшие:",
|
||||
|
|
|
|||
|
|
@ -1977,7 +1977,6 @@
|
|||
"NO_PLUGINS_INSTALLED": "Momentálne nie sú nainštalované žiadne pluginy",
|
||||
"PLUGINS": "Pluginy",
|
||||
"PRIVACY_POLICY": "Privacy Policy",
|
||||
"PRODUCTIVITY_HELPER": "Productivity Helper",
|
||||
"PROJECT_SETTINGS": "Project Specific Settings",
|
||||
"PROVIDE_FEEDBACK": "Provide Feedback",
|
||||
"SYNC_EXPORT": "Sync & Export",
|
||||
|
|
|
|||
|
|
@ -1824,7 +1824,6 @@
|
|||
"NO_PLUGINS_INSTALLED": "Inga plugins är för närvarande installerade",
|
||||
"PLUGINS": "Plugins",
|
||||
"PRIVACY_POLICY": "Sekretesspolicy",
|
||||
"PRODUCTIVITY_HELPER": "Produktivitetshjälp",
|
||||
"PROJECT_SETTINGS": "Projektspecifika inställningar",
|
||||
"PROVIDE_FEEDBACK": "Ge feedback",
|
||||
"SYNC_EXPORT": "Synkronisera och exportera",
|
||||
|
|
|
|||
|
|
@ -1956,7 +1956,6 @@
|
|||
"NO_PLUGINS_INSTALLED": "Şu an yüklenmiş eklenti yok.",
|
||||
"PLUGINS": "Eklentiler",
|
||||
"PRIVACY_POLICY": "Gizlilik sözleşmesi",
|
||||
"PRODUCTIVITY_HELPER": "Verimlilik Yardımcısı",
|
||||
"PROJECT_SETTINGS": "Projeye Özel Ayarlar",
|
||||
"PROVIDE_FEEDBACK": "Geribildirim sağlayın",
|
||||
"SYNC_EXPORT": "Senkronize Et ve Dışa Aktar",
|
||||
|
|
|
|||
|
|
@ -1539,7 +1539,6 @@
|
|||
"PS": {
|
||||
"GLOBAL_SETTINGS": "Глобальні налаштування",
|
||||
"PRIVACY_POLICY": "Політика конфіденційності",
|
||||
"PRODUCTIVITY_HELPER": "Помічник продуктивності",
|
||||
"PROJECT_SETTINGS": "Налаштування конкретного проекту",
|
||||
"PROVIDE_FEEDBACK": "Надати відгук",
|
||||
"SYNC_EXPORT": "Синхронізація та експорт",
|
||||
|
|
|
|||
|
|
@ -2379,7 +2379,6 @@
|
|||
"NO_PLUGINS_INSTALLED": "当前未安装任何插件",
|
||||
"PLUGINS": "插件",
|
||||
"PRIVACY_POLICY": "隐私政策",
|
||||
"PRODUCTIVITY_HELPER": "生产力助手",
|
||||
"PROJECT_SETTINGS": "项目特定设置",
|
||||
"PROVIDE_FEEDBACK": "提供反馈",
|
||||
"RELOAD": "重新加载",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue