mirror of https://github.com/keeweb/keeweb.git
String globalization
This commit is contained in:
parent
dd2f94978e
commit
e0f5f49255
|
@ -7,7 +7,8 @@ var AppModel = require('./models/app-model'),
|
|||
Alerts = require('./comp/alerts'),
|
||||
DropboxLink = require('./comp/dropbox-link'),
|
||||
Updater = require('./comp/updater'),
|
||||
ThemeChanger = require('./util/theme-changer');
|
||||
ThemeChanger = require('./util/theme-changer'),
|
||||
Locale = require('./util/locale');
|
||||
|
||||
$(function() {
|
||||
if (location.href.indexOf('state=') >= 0) {
|
||||
|
@ -24,14 +25,10 @@ $(function() {
|
|||
ThemeChanger.setTheme(appModel.settings.get('theme'));
|
||||
}
|
||||
if (['https:', 'file:', 'app:'].indexOf(location.protocol) < 0 && !localStorage.disableSecurityCheck) {
|
||||
Alerts.error({ header: 'Not Secure!', icon: 'user-secret', esc: false, enter: false, click: false,
|
||||
body: 'You have loaded this app with insecure connection. ' +
|
||||
'Someone may be watching you and stealing your passwords. ' +
|
||||
'We strongly advice you to stop, unless you clearly understand what you\'re doing.' +
|
||||
'<br/><br/>' +
|
||||
'Yes, your database is encrypted but no one can guarantee that the app has not been modified on the way to you.',
|
||||
Alerts.error({ header: Locale.appSecWarn, icon: 'user-secret', esc: false, enter: false, click: false,
|
||||
body: Locale.appSecWarnBody1 + '<br/><br/>' + Locale.appSecWarnBody2,
|
||||
buttons: [
|
||||
{ result: '', title: 'I understand the risks, continue', error: true }
|
||||
{ result: '', title: Locale.appSecWarnBtn, error: true }
|
||||
],
|
||||
complete: showApp
|
||||
});
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
'use strict';
|
||||
|
||||
var ModalView = require('../views/modal-view');
|
||||
var ModalView = require('../views/modal-view'),
|
||||
Locale = require('../util/locale');
|
||||
|
||||
var Alerts = {
|
||||
alertDisplayed: false,
|
||||
|
||||
buttons: {
|
||||
ok: {result: 'yes', title: 'OK'},
|
||||
yes: {result: 'yes', title: 'Yes'},
|
||||
no: {result: '', title: 'No'}
|
||||
ok: {result: 'yes', title: Locale.alertOk},
|
||||
yes: {result: 'yes', title: Locale.alertYes},
|
||||
no: {result: '', title: Locale.alertNo}
|
||||
},
|
||||
|
||||
alert: function(config) {
|
||||
|
@ -31,7 +32,7 @@ var Alerts = {
|
|||
|
||||
notImplemented: function() {
|
||||
this.alert({
|
||||
header: 'Not Implemented',
|
||||
header: Locale.notImplemented,
|
||||
body: '',
|
||||
icon: 'exclamation-triangle',
|
||||
buttons: [this.buttons.ok],
|
||||
|
|
|
@ -4,6 +4,7 @@ var Dropbox = require('dropbox'),
|
|||
Alerts = require('./alerts'),
|
||||
Launcher = require('./launcher'),
|
||||
Logger = require('../util/logger'),
|
||||
Locale = require('../util/locale'),
|
||||
Links = require('../const/links');
|
||||
|
||||
var logger = new Logger('dropbox');
|
||||
|
@ -134,9 +135,9 @@ var DropboxLink = {
|
|||
if (!isValidKey()) {
|
||||
Alerts.error({
|
||||
icon: 'dropbox',
|
||||
header: 'Dropbox not configured',
|
||||
body: 'So, you are using KeeWeb on your own server? Good!<br/>' +
|
||||
'<a href="' + Links.SelfHostedDropbox + '" target="blank">Some configuration</a> is required to make Dropbox work, it\'s just 3 steps away.'
|
||||
header: Locale.dropboxNotConfigured,
|
||||
body: Locale.dropboxNotConfiguredBody1 + '<br/>' + Locale.dropboxNotConfiguredBody2.replace('{}',
|
||||
'<a href="' + Links.SelfHostedDropbox + '" target="blank">' + Locale.dropboxNotConfiguredLink + '</a>')
|
||||
});
|
||||
return complete(DropboxCustomErrors.BadKey);
|
||||
}
|
||||
|
@ -166,9 +167,9 @@ var DropboxLink = {
|
|||
if (!Alerts.alertDisplayed) {
|
||||
Alerts.yesno({
|
||||
icon: 'dropbox',
|
||||
header: 'Dropbox Login',
|
||||
body: 'To continue, you have to sign in to Dropbox.',
|
||||
buttons: [{result: 'yes', title: 'Sign In'}, {result: '', title: 'Cancel'}],
|
||||
header: Locale.dropboxLogin,
|
||||
body: Locale.dropboxLoginBody,
|
||||
buttons: [{result: 'yes', title: Locale.alertSignIn}, {result: '', title: Locale.alertCancel}],
|
||||
success: (function () {
|
||||
this.authenticate(function (err) { callback(!err); });
|
||||
}).bind(this),
|
||||
|
@ -181,42 +182,42 @@ var DropboxLink = {
|
|||
break;
|
||||
case Dropbox.ApiError.NOT_FOUND:
|
||||
alertCallback({
|
||||
header: 'Dropbox Sync Error',
|
||||
body: 'The file was not found. Has it been removed from another computer?'
|
||||
header: Locale.dropboxSyncError,
|
||||
body: Locale.dropboxNotFoundBody
|
||||
});
|
||||
break;
|
||||
case Dropbox.ApiError.OVER_QUOTA:
|
||||
alertCallback({
|
||||
header: 'Dropbox Full',
|
||||
body: 'Your Dropbox is full, there\'s no space left anymore.'
|
||||
header: Locale.dropboxFull,
|
||||
body: Locale.dropboxFullBody
|
||||
});
|
||||
break;
|
||||
case Dropbox.ApiError.RATE_LIMITED:
|
||||
alertCallback({
|
||||
header: 'Dropbox Sync Error',
|
||||
body: 'Too many requests to Dropbox have been made by this app. Please, try again later.'
|
||||
header: Locale.dropboxSyncError,
|
||||
body: Locale.dropboxRateLimitedBody
|
||||
});
|
||||
break;
|
||||
case Dropbox.ApiError.NETWORK_ERROR:
|
||||
alertCallback({
|
||||
header: 'Dropbox Sync Network Error',
|
||||
body: 'Network error occured during Dropbox sync. Please, check your connection and try again.'
|
||||
header: Locale.dropboxNetError,
|
||||
body: Locale.dropboxNetErrorBody
|
||||
});
|
||||
break;
|
||||
case Dropbox.ApiError.INVALID_PARAM:
|
||||
case Dropbox.ApiError.OAUTH_ERROR:
|
||||
case Dropbox.ApiError.INVALID_METHOD:
|
||||
alertCallback({
|
||||
header: 'Dropbox Sync Error',
|
||||
body: 'Something went wrong during Dropbox sync. Please, try again later. Error code: ' + err.status
|
||||
header: Locale.dropboxSyncError,
|
||||
body: Locale.dropboxErrorBody + err.status
|
||||
});
|
||||
break;
|
||||
case Dropbox.ApiError.CONFLICT:
|
||||
break;
|
||||
default:
|
||||
alertCallback({
|
||||
header: 'Dropbox Sync Error',
|
||||
body: 'Something went wrong during Dropbox sync. Please, try again later. Error: ' + err
|
||||
header: Locale.dropboxSyncError,
|
||||
body: Locale.dropboxErrorRepeatBody + err
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
var Backbone = require('backbone');
|
||||
var Backbone = require('backbone'),
|
||||
Locale = require('../util/locale');
|
||||
var Launcher;
|
||||
|
||||
if (window.process && window.process.versions && window.process.versions.electron) {
|
||||
|
@ -28,9 +29,9 @@ if (window.process && window.process.versions && window.process.versions.electro
|
|||
defaultPath = this.req('path').join(homePath, defaultPath);
|
||||
}
|
||||
this.remReq('dialog').showSaveDialog({
|
||||
title: 'Save Passwords Database',
|
||||
title: Locale.launcherSave,
|
||||
defaultPath: defaultPath,
|
||||
filters: [{ name: 'KeePass files', extensions: ['kdbx'] }]
|
||||
filters: [{ name: Locale.launcherFileFilter, extensions: ['kdbx'] }]
|
||||
}, cb);
|
||||
},
|
||||
getUserDataPath: function(fileName) {
|
||||
|
|
|
@ -4,3 +4,4 @@ require('./cmp');
|
|||
require('./ifeq');
|
||||
require('./ifneq');
|
||||
require('./ifemptyoreq');
|
||||
require('./res');
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
'use strict';
|
||||
|
||||
var Handlebars = require('hbs'),
|
||||
Locale = require('../util/locale');
|
||||
|
||||
Handlebars.registerHelper('res', function(key, options) {
|
||||
var value = Locale[key];
|
||||
if (value) {
|
||||
var ix = value.indexOf('{}');
|
||||
if (ix >= 0) {
|
||||
value = value.replace('{}', options.fn(this));
|
||||
}
|
||||
}
|
||||
return value;
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('Res', function(key) {
|
||||
var value = Locale[key];
|
||||
if (value) {
|
||||
value = value[0].toUpperCase() + value.substr(1);
|
||||
}
|
||||
return value;
|
||||
});
|
|
@ -4,6 +4,7 @@ var Backbone = require('backbone'),
|
|||
MenuSectionCollection = require('../../collections/menu/menu-section-collection'),
|
||||
MenuSectionModel = require('./menu-section-model'),
|
||||
GroupsMenuModel = require('./groups-menu-model'),
|
||||
Locale = require('../../util/locale'),
|
||||
Keys = require('../../const/keys'),
|
||||
Colors = require('../../const/colors');
|
||||
|
||||
|
@ -16,17 +17,18 @@ var MenuModel = Backbone.Model.extend({
|
|||
|
||||
initialize: function() {
|
||||
this.menus = {};
|
||||
this.allItemsSection = new MenuSectionModel([{ title: 'All Items', icon: 'th-large', active: true, shortcut: Keys.DOM_VK_A, filterKey: '*' }]);
|
||||
this.allItemsSection = new MenuSectionModel([{ title: Locale.menuAllItems, icon: 'th-large', active: true,
|
||||
shortcut: Keys.DOM_VK_A, filterKey: '*' }]);
|
||||
this.groupsSection = new GroupsMenuModel();
|
||||
this.colorsSection = new MenuSectionModel([{ title: 'Colors', icon: 'bookmark', shortcut: Keys.DOM_VK_C, cls: 'menu__item-colors',
|
||||
filterKey: 'color', filterValue: true }]);
|
||||
this.colorsSection = new MenuSectionModel([{ title: Locale.menuColors, icon: 'bookmark', shortcut: Keys.DOM_VK_C,
|
||||
cls: 'menu__item-colors', filterKey: 'color', filterValue: true }]);
|
||||
this.colorsItem = this.colorsSection.get('items').models[0];
|
||||
var defTags = [{ title: 'Tags', icon: 'tags', defaultItem: true,
|
||||
disabled: { header: 'No tags', body: 'You can add new tags while editing fields, in tags section.', icon: 'tags' } }];
|
||||
var defTags = [{ title: Locale.menuTags, icon: 'tags', defaultItem: true,
|
||||
disabled: { header: Locale.menuAlertNoTags, body: Locale.menuAlertNoTagsBody, icon: 'tags' } }];
|
||||
this.tagsSection = new MenuSectionModel(defTags);
|
||||
this.tagsSection.set({ scrollable: true, drag: true });
|
||||
this.tagsSection.defaultItems = defTags;
|
||||
this.trashSection = new MenuSectionModel([{ title: 'Trash', icon: 'trash', shortcut: Keys.DOM_VK_D,
|
||||
this.trashSection = new MenuSectionModel([{ title: Locale.menuTrash, icon: 'trash', shortcut: Keys.DOM_VK_D,
|
||||
filterKey: 'trash', filterValue: true, drop: true }]);
|
||||
Colors.AllColors.forEach(function(color) { this.colorsSection.get('items').models[0]
|
||||
.addOption({ cls: 'fa ' + color + '-color', value: color, filterValue: color }); }, this);
|
||||
|
@ -38,10 +40,10 @@ var MenuModel = Backbone.Model.extend({
|
|||
this.trashSection
|
||||
]);
|
||||
|
||||
this.generalSection = new MenuSectionModel([{ title: 'General', icon: 'cog', page: 'general', active: true }]);
|
||||
this.shortcutsSection = new MenuSectionModel([{ title: 'Shortcuts', icon: 'keyboard-o', page: 'shortcuts' }]);
|
||||
this.aboutSection = new MenuSectionModel([{ title: 'About', icon: 'info', page: 'about' }]);
|
||||
this.helpSection = new MenuSectionModel([{ title: 'Help', icon: 'question', page: 'help' }]);
|
||||
this.generalSection = new MenuSectionModel([{ title: Locale.menuSetGeneral, icon: 'cog', page: 'general', active: true }]);
|
||||
this.shortcutsSection = new MenuSectionModel([{ title: Locale.menuSetShortcuts, icon: 'keyboard-o', page: 'shortcuts' }]);
|
||||
this.aboutSection = new MenuSectionModel([{ title: Locale.menuSetAbout, icon: 'info', page: 'about' }]);
|
||||
this.helpSection = new MenuSectionModel([{ title: Locale.menuSetHelp, icon: 'question', page: 'help' }]);
|
||||
this.filesSection = new MenuSectionModel();
|
||||
this.filesSection.set({ scrollable: true, grow: true });
|
||||
this.menus.settings = new MenuSectionCollection([
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
var Format = require('../util/format');
|
||||
var Format = require('../util/format'),
|
||||
Locale = require('../util/locale');
|
||||
|
||||
var EntryPresenter = function(descField, noColor, activeEntryId) {
|
||||
this.entry = null;
|
||||
|
@ -33,19 +34,19 @@ EntryPresenter.prototype = {
|
|||
get tags() { return this.entry ? this.entry.tags : false; },
|
||||
get description() {
|
||||
if (!this.entry) {
|
||||
return '[Group]';
|
||||
return '[' + Locale.listGroup + ']';
|
||||
}
|
||||
switch (this.descField) {
|
||||
case 'website':
|
||||
return this.url || '(no website)';
|
||||
return this.url || '(' + Locale.listNoWebsite + ')';
|
||||
case 'user':
|
||||
return this.user || '(no user)';
|
||||
return this.user || '(' + Locale.listNoUser + ')';
|
||||
case 'created':
|
||||
return this.created;
|
||||
case 'updated':
|
||||
return this.updated;
|
||||
case 'attachments':
|
||||
return this.entry.attachments.map(function(a) { return a.title; }).join(', ') || '(no attachments)';
|
||||
return this.entry.attachments.map(function(a) { return a.title; }).join(', ') || '(' + Locale.listNoAttachments + ')';
|
||||
default:
|
||||
return this.notes || this.url || this.user;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ var Format = {
|
|||
':' + this.pad(dt.getSeconds(), 2) : '';
|
||||
},
|
||||
dStr: function(dt) {
|
||||
return dt ? dt.getDate() + ' ' + Locale.MonthsShort[dt.getMonth()] + ' ' + dt.getFullYear() : '';
|
||||
return dt ? dt.getDate() + ' ' + Locale.monthsShort[dt.getMonth()] + ' ' + dt.getFullYear() : '';
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,10 +1,300 @@
|
|||
'use strict';
|
||||
|
||||
var Locale = {
|
||||
Months: ['January','February','March','April','May','June','July','August','September','October','November','December'],
|
||||
MonthsShort: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
|
||||
Weekdays: ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
|
||||
WeekdaysShort: ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']
|
||||
months: ['January','February','March','April','May','June','July','August','September','October','November','December'],
|
||||
monthsShort: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
|
||||
weekdays: ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
|
||||
weekdaysShort: ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'],
|
||||
|
||||
retToApp: 'return to app',
|
||||
name: 'name',
|
||||
icon: 'icon',
|
||||
title: 'title',
|
||||
user: 'user',
|
||||
website: 'website',
|
||||
tags: 'tags',
|
||||
notes: 'notes',
|
||||
noTitle: 'no title',
|
||||
or: 'or',
|
||||
notImplemented: 'Not Implemented',
|
||||
|
||||
menuAllItems: 'All Items',
|
||||
menuColors: 'Colors',
|
||||
menuTags: 'Tags',
|
||||
menuTrash: 'Trash',
|
||||
menuSetGeneral: 'General',
|
||||
menuSetShortcuts: 'Shortcuts',
|
||||
menuSetHelp: 'Help',
|
||||
menuSetAbout: 'About',
|
||||
menuAlertNoTags: 'No tags',
|
||||
menuAlertNoTagsBody: 'You can add new tags while editing fields, in tags section.',
|
||||
menuEmptyTrash: 'Empty Trash',
|
||||
menuEmptyTrashAlert: 'Empty Trash?',
|
||||
menuEmptyTrashAlertBody: 'You will not be able to put items back',
|
||||
|
||||
alertYes: 'Yes',
|
||||
alertNo: 'No',
|
||||
alertOk: 'OK',
|
||||
alertCancel: 'Cancel',
|
||||
alertSignIn: 'Sign In',
|
||||
alertCopy: 'Copy',
|
||||
alertClose: 'Close',
|
||||
|
||||
footerOpen: 'Open / New',
|
||||
|
||||
genLen: 'Length',
|
||||
grpTitle: 'Group',
|
||||
grpSearch: 'Enable searching entries in this group',
|
||||
|
||||
iconFavTitle: 'Download and use website favicon',
|
||||
iconSelCustom: 'Select custom icon',
|
||||
|
||||
listEmptyTitle: 'Empty',
|
||||
listEmptyAdd: 'add with {} button above',
|
||||
listGroup: 'Group',
|
||||
listNoWebsite: 'no website',
|
||||
listNoUser: 'no user',
|
||||
listNoAttachments: 'no attachments',
|
||||
|
||||
searchAddNew: 'Add New',
|
||||
searchSort: 'Sort',
|
||||
searchTitle: 'Title',
|
||||
searchWebsite: 'Website',
|
||||
searchUser: 'User',
|
||||
searchCreated: 'Created',
|
||||
searchUpdated: 'Updated',
|
||||
searchAttachments: 'Attachments',
|
||||
searchAZ: 'A → Z',
|
||||
searchZA: 'Z → A',
|
||||
searchON: 'Old → New',
|
||||
searchNO: 'New → Old',
|
||||
searchShiftClickOr: 'shift-click or',
|
||||
|
||||
openOpen: 'Open',
|
||||
openNew: 'New',
|
||||
openDemo: 'Demo',
|
||||
openCaps: 'Caps Lock is on',
|
||||
openKeyFile: 'key file',
|
||||
openKeyFileDropbox: '(from dropbox)',
|
||||
openDropHere: 'drop files here',
|
||||
openFailedRead: 'Failed to read file',
|
||||
openNothingFound: 'Nothing found',
|
||||
openNothingFoundBody: 'You have no files in your Dropbox which could be opened.',
|
||||
openNothingFoundBodyAppFolder: 'Files are searched inside app folder in your Dropbox.',
|
||||
openSelectFile: 'Select a file',
|
||||
openSelectFileBody: 'Select a file from your Dropbox which you would like to open',
|
||||
openPassFor: 'Password for',
|
||||
|
||||
detAttDownload: 'Shift-click attachment button to download or ',
|
||||
detAttDelToRemove: 'Delete to remove',
|
||||
detEmpty: 'Your passwords will be displayed here',
|
||||
detGroupRestore: 'To restore this group, please drag it to any group outside trash',
|
||||
detHistoryClickPoint: 'Click entry history timeline point to view state',
|
||||
detHistoryReturn: 'return to entry',
|
||||
detHistoryRevert: 'Revert to state',
|
||||
detHistoryDel: 'Delete state',
|
||||
detHistoryDiscard: 'Discard changes',
|
||||
detHistoryEmpty: 'empty',
|
||||
detHistoryModified: 'modified',
|
||||
detHistoryRec: 'record',
|
||||
detHistoryRecs: 'records',
|
||||
detHistoryVersion: 'Version',
|
||||
detHistorySaved: 'Saved',
|
||||
detHistoryTitle: 'Title',
|
||||
detHistoryNoTitle: 'no title',
|
||||
detHistoryCurState: 'current state',
|
||||
detHistoryCurUnsavedState: 'current unsaved state',
|
||||
detBackToList: 'back to list',
|
||||
detSetIconColor: 'Change icon color',
|
||||
detSetIcon: 'Change icon',
|
||||
detDropAttachments: 'drop attachments here',
|
||||
detDelEntry: 'Delete',
|
||||
detDelEntryPerm: 'Delete permanently',
|
||||
detUser: 'User',
|
||||
detPassword: 'Password',
|
||||
detWebsite: 'Website',
|
||||
detNotes: 'Notes',
|
||||
detTags: 'Tags',
|
||||
detExpires: 'Expires',
|
||||
detExpired: 'expired',
|
||||
detFile: 'File',
|
||||
detCreated: 'Created',
|
||||
detUpdated: 'Updated',
|
||||
detHistory: 'History',
|
||||
detNetField: 'New Field',
|
||||
detAddField: 'add field',
|
||||
detAttachments: 'Attachments',
|
||||
detDelFromTrash: 'Delete from trash?',
|
||||
detDelFromTrashBody: 'You will not be able to put it back.',
|
||||
detDelFromTrashBodyHint: 'To quickly remove all items from trash, click empty icon in Trash menu.',
|
||||
|
||||
appSecWarn: 'Not Secure!',
|
||||
appSecWarnBody1: 'You have loaded this app with insecure connection. ' +
|
||||
'Someone may be watching you and stealing your passwords. ' +
|
||||
'We strongly advice you to stop, unless you clearly understand what you\'re doing.',
|
||||
appSecWarnBody2: 'Yes, your database is encrypted but no one can guarantee that the app has not been modified on the way to you.',
|
||||
appSecWarnBtn: 'I understand the risks, continue',
|
||||
appUnsavedWarn: 'Unsaved changes!',
|
||||
appUnsavedWarnBody: 'You have unsaved files, all changes will be lost.',
|
||||
appExitBtn: 'Exit and discard unsaved changes',
|
||||
appDontExitBtn: 'Don\'t exit',
|
||||
appUnsavedCloseMsg: 'You have unsaved files, all changes will be lost.',
|
||||
appCannotLockAutoInit: 'The app cannot be locked because auto save is disabled.',
|
||||
appCannotLock: 'You have unsaved changes that will be lost. Continue?',
|
||||
appSaveChangesBtn: 'Save changes',
|
||||
appDiscardChangesBtn: 'Discard changes',
|
||||
appAutoSave: 'Save changes automatically',
|
||||
appSaveError: 'Save Error',
|
||||
appSaveErrorBody: 'Failed to auto-save file',
|
||||
appSaveErrorBodyMul: 'Failed to auto-save files:',
|
||||
|
||||
setGenTitle: 'General Settings',
|
||||
setGenUpdate: 'Update',
|
||||
setGenNewVersion: 'New app version was released and downloaded',
|
||||
setGenReleaseNotes: 'View release notes',
|
||||
setGenReloadTpUpdate: 'Reload to update',
|
||||
setGenUpdateManual: 'New version has been released. It will check for updates and install them automatically ' +
|
||||
'but auto-upgrading from your version is impossible.',
|
||||
setGenDownloadUpdate: 'Download update',
|
||||
setGenUpdateAuto: 'Download and install automatically',
|
||||
setGenUpdateCheck: 'Check but don\'t install',
|
||||
setGenNoUpdate: 'Never check for updates',
|
||||
setGenUpdateChecking: 'Checking for updates',
|
||||
setGenCheckUpdate: 'Check for updates',
|
||||
setGenErrorChecking: 'Error checking for updates',
|
||||
setGenLastCheckSuccess: 'Last successful check was at {}',
|
||||
setGenLastCheckVer: 'the latest version was {}',
|
||||
setGenCheckedAt: 'Checked at',
|
||||
setGenLatestVer: 'you are using the latest version',
|
||||
setGenNewVer: 'new version {} available, released at',
|
||||
setGenDownloadingUpdate: 'Downloading update...',
|
||||
setGenExtractingUpdate: 'Extracting update...',
|
||||
setGenCheckErr: 'There was an error downloading new version',
|
||||
setGenNeverChecked: 'Never checked for updates',
|
||||
setGenRestartToUpdate: 'Restart to update',
|
||||
setGenDownloadAndRestart: 'Download update and restart',
|
||||
setGenAppearance: 'Appearance',
|
||||
setGenTheme: 'Theme',
|
||||
setGenShowSubgroups: 'Show entries from all subgroups',
|
||||
setGenTableView: 'Entries list table view',
|
||||
setGenColorfulIcons: 'Colorful custom icons in list',
|
||||
setGenAutoSync: 'Automatically save and sync',
|
||||
setGenLockInactive: 'Auto-lock if the app is inactive',
|
||||
setGenNoAutoLock: 'Don\'t auto-lock',
|
||||
setGenLockMinutes: 'In {} minutes',
|
||||
setGenLockHour: 'In an hour',
|
||||
setGenClearClip: 'Clear clipboard after copy',
|
||||
setGenNoClear: 'Don\'t clear',
|
||||
setGenClearSeconds: 'In {} seconds',
|
||||
setGenClearMinute: 'In a minute',
|
||||
setGenMinInstead: 'Minimize app instead of close',
|
||||
setGenLockMinimize: 'Auto-lock on minimize',
|
||||
setGenAdvanced: 'Advanced',
|
||||
setGenDevTools: 'Show dev tools',
|
||||
|
||||
setFilePath: 'File path',
|
||||
setFileStorage: 'This file is opened from {}.',
|
||||
setFileIntl: 'This file is stored in internal app storage',
|
||||
setFileLocalHint: 'Want to work seamlessly with local files?',
|
||||
setFileDownloadApp: 'Download a desktop app',
|
||||
setFileSave: 'Save',
|
||||
setFileSyncWith: 'Sync with {}',
|
||||
setFileSaveFile: 'Save to file',
|
||||
setFileExportXml: 'Export to XML',
|
||||
setFileClose: 'Close',
|
||||
setFileSync: 'Sync',
|
||||
setFileLastSync: 'Last sync',
|
||||
setFileLastSyncUnknown: 'unknown',
|
||||
setFileSyncInProgress: 'sync in progress',
|
||||
setFileSyncError: 'Sync error',
|
||||
setFileSettings: 'Settings',
|
||||
setFilePass: 'Master password',
|
||||
setFilePassChanged: 'password was changed; leave the field blank to use old password',
|
||||
setFileKeyFile: 'Key file',
|
||||
setFileSelKeyFile: 'Select a key file',
|
||||
setFileNames: 'Names',
|
||||
setFileName: 'Name',
|
||||
setFileDefUser: 'Default username',
|
||||
setFileHistory: 'History',
|
||||
setFileEnableTrash: 'Enable trash',
|
||||
setFileHistLen: 'History length, keep last records per entry',
|
||||
resFileHistSize: 'History size, total MB per file',
|
||||
setFileAdvanced: 'Advanced',
|
||||
setFileRounds: 'Key encryption rounds',
|
||||
setFileUseKeyFile: 'Use key file',
|
||||
setFileUseGenKeyFile: 'Use generated key file',
|
||||
setFileUseOldKeyFile: 'Use old key file',
|
||||
setFileGenKeyFile: 'Generate new key file',
|
||||
setFileDontUseKeyFile: 'Don\'t use key file',
|
||||
setFileEmptyPass: 'Empty password',
|
||||
setFileEmptyPassBody: 'Saving database with empty password makes it completely unprotected. Do you really want to do it?',
|
||||
setFileSaveError: 'Save error',
|
||||
setFileSaveErrorBody: 'Error saving to file',
|
||||
setFileAlreadyExists: 'Already exists',
|
||||
setFileAlreadyExistsBody: 'File {} already exists in your Dropbox. Overwrite it?',
|
||||
setFileUnsaved: 'Unsaved changes',
|
||||
setFileUnsavedBody: 'There are unsaved changes in this file',
|
||||
setFileCloseNoSave: 'Close and lose changes',
|
||||
setFileDontClose: 'Don\t close',
|
||||
|
||||
setShTitle: 'Shortcuts',
|
||||
setShShowAll: 'show all items',
|
||||
setShColors: 'show items with colors',
|
||||
setShTrash: 'go to trash',
|
||||
setShFind: 'search, or just start typing',
|
||||
setShClearSearch: 'clear search',
|
||||
setShEntry: 'go to entry',
|
||||
setShCopy: 'copy password or selected field',
|
||||
setShPrev: 'go to previous item',
|
||||
setShNext: 'go to next item',
|
||||
setShCreateEntry: 'create entry',
|
||||
setShOpen: 'open / new',
|
||||
setShSave: 'save all files',
|
||||
setShGen: 'generate password',
|
||||
|
||||
setAboutTitle: 'About',
|
||||
setAboutBuilt: 'This app is built with these awesome tools',
|
||||
setAboutLic: 'License',
|
||||
setAboutLicComment: 'The app itself and all included components which are not in public domain are licensed under MIT license',
|
||||
setAboutFirst: 'This is an open-source app created by {}',
|
||||
setAboutSecond: ' and licensed under {}.',
|
||||
setAboutSource: 'The source code and issues are on {}.',
|
||||
|
||||
setHelpTitle: 'Help',
|
||||
setHelpFormat: 'File Format',
|
||||
setHelpFormatBody: 'This is a port of {} app built with web technologies. ' +
|
||||
'It understands files in KeePass format (kdbx). You can create such files (password databases) either in KeePass, ' +
|
||||
'or in this app. The file format is 100% compatible and should be understood by both apps.',
|
||||
setHelpProblems: 'Problems?',
|
||||
setHelpProblems1: 'If something goes wrong, please {} ',
|
||||
setHelpProblems2: 'or {}',
|
||||
setHelpOpenIssue: 'open an issue on GitHub',
|
||||
setHelpContactLink: 'contact a developer directly',
|
||||
setHelpAppInfo: 'App information',
|
||||
setHelpOtherPlatforms: 'Other platforms',
|
||||
setHelpDesktopApps: 'Desktop apps',
|
||||
setHelpWebApp: 'Web app',
|
||||
setHelpUpdates: 'Updates',
|
||||
setHelpTwitter: 'App twitter',
|
||||
|
||||
dropboxNotConfigured: 'Dropbox not configured',
|
||||
dropboxNotConfiguredBody1: 'So, you are using KeeWeb on your own server? Good!',
|
||||
dropboxNotConfiguredBody2: '{} is required to make Dropbox work, it\'s just 3 steps away.',
|
||||
dropboxNotConfiguredLink: 'Some configuration',
|
||||
dropboxLogin: 'Dropbox Login',
|
||||
dropboxLoginBody: 'To continue, you have to sign in to Dropbox.',
|
||||
dropboxSyncError: 'Dropbox Sync Error',
|
||||
dropboxNotFoundBody: 'The file was not found. Has it been removed from another computer?',
|
||||
dropboxFull: 'Dropbox Full',
|
||||
dropboxFullBody: 'Your Dropbox is full, there\'s no space left anymore.',
|
||||
dropboxRateLimitedBody: 'Too many requests to Dropbox have been made by this app. Please, try again later.',
|
||||
dropboxNetError: 'Dropbox Sync Network Error',
|
||||
dropboxNetErrorBody: 'Network error occured during Dropbox sync. Please, check your connection and try again.',
|
||||
dropboxErrorBody: 'Something went wrong during Dropbox sync. Please, try again later. Error code: ',
|
||||
dropboxErrorRepeatBody: 'Something went wrong during Dropbox sync. Please, try again later. Error: ',
|
||||
|
||||
launcherSave: 'Save Passwords Database',
|
||||
launcherFileFilter: 'KeePass files'
|
||||
};
|
||||
|
||||
module.exports = Locale;
|
||||
|
|
|
@ -17,6 +17,7 @@ var Backbone = require('backbone'),
|
|||
IdleTracker = require('../comp/idle-tracker'),
|
||||
Launcher = require('../comp/launcher'),
|
||||
ThemeChanger = require('../util/theme-changer'),
|
||||
Locale = require('../util/locale'),
|
||||
UpdateModel = require('../models/update-model');
|
||||
|
||||
var AppView = Backbone.View.extend({
|
||||
|
@ -224,9 +225,9 @@ var AppView = Backbone.View.extend({
|
|||
var that = this;
|
||||
that.exitAlertShown = true;
|
||||
Alerts.yesno({
|
||||
header: 'Unsaved changes!',
|
||||
body: 'You have unsaved files, all changes will be lost.',
|
||||
buttons: [{result: 'yes', title: 'Exit and discard unsaved changes'}, {result: '', title: 'Don\'t exit'}],
|
||||
header: Locale.appUnsavedWarn,
|
||||
body: Locale.appUnsavedWarnBody,
|
||||
buttons: [{result: 'yes', title: Locale.appExitBtn}, {result: '', title: Locale.appDontExitBtn}],
|
||||
success: function () {
|
||||
Launcher.exit();
|
||||
},
|
||||
|
@ -240,7 +241,7 @@ var AppView = Backbone.View.extend({
|
|||
}
|
||||
return Launcher.preventExit(e);
|
||||
}
|
||||
return 'You have unsaved files, all changes will be lost.';
|
||||
return Locale.appUnsavedCloseMsg;
|
||||
} else if (Launcher && !Launcher.exitRequested && !Launcher.restartPending &&
|
||||
Launcher.canMinimize() && this.model.settings.get('minimizeOnClose')) {
|
||||
Launcher.minimizeApp();
|
||||
|
@ -294,18 +295,17 @@ var AppView = Backbone.View.extend({
|
|||
if (this.model.settings.get('autoSave')) {
|
||||
this.saveAndLock(autoInit);
|
||||
} else {
|
||||
var message = autoInit ? 'The app cannot be locked because auto save is disabled.'
|
||||
: 'You have unsaved changes that will be lost. Continue?';
|
||||
var message = autoInit ? Locale.appCannotLockAutoInit : Locale.appCannotLock;
|
||||
Alerts.alert({
|
||||
icon: 'lock',
|
||||
header: 'Lock',
|
||||
body: message,
|
||||
buttons: [
|
||||
{ result: 'save', title: 'Save changes' },
|
||||
{ result: 'discard', title: 'Discard changes', error: true },
|
||||
{ result: '', title: 'Cancel' }
|
||||
{ result: 'save', title: Locale.appSaveChangesBtn },
|
||||
{ result: 'discard', title: Locale.appDiscardChangesBtn, error: true },
|
||||
{ result: '', title: Locale.alertCancel }
|
||||
],
|
||||
checkbox: 'Save changes automatically',
|
||||
checkbox: Locale.appAutoSave,
|
||||
success: function(result, autoSaveChecked) {
|
||||
if (result === 'save') {
|
||||
if (autoSaveChecked) {
|
||||
|
@ -344,9 +344,10 @@ var AppView = Backbone.View.extend({
|
|||
if (--pendingCallbacks === 0) {
|
||||
if (errorFiles.length && that.model.files.hasDirtyFiles()) {
|
||||
if (!Alerts.alertDisplayed) {
|
||||
var alertBody = errorFiles.length > 1 ? Locale.appSaveErrorBodyMul : Locale.appSaveErrorBody;
|
||||
Alerts.error({
|
||||
header: 'Save Error',
|
||||
body: 'Failed to auto-save file' + (errorFiles.length > 1 ? 's: ' : '') + ' ' + errorFiles.join(', ')
|
||||
header: Locale.appSaveError,
|
||||
body: alertBody + ' ' + errorFiles.join(', ')
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -4,6 +4,7 @@ var Backbone = require('backbone'),
|
|||
KeyHandler = require('../../comp/key-handler'),
|
||||
Keys = require('../../const/keys'),
|
||||
Format = require('../../util/format'),
|
||||
Locale = require('../../util/locale'),
|
||||
Alerts = require('../../comp/alerts'),
|
||||
FieldViewReadOnly = require('../fields/field-view-read-only'),
|
||||
FieldViewReadOnlyRaw = require('../fields/field-view-read-only-raw');
|
||||
|
@ -82,25 +83,26 @@ var DetailsHistoryView = Backbone.View.extend({
|
|||
this.removeFieldViews();
|
||||
this.bodyEl.html('');
|
||||
var colorCls = this.record.color ? this.record.color + '-color' : '';
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: 'Rev', title: 'Version', value: ix + 1 } }));
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: 'Updated', title: 'Saved',
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: 'Rev', title: Locale.detHistoryVersion, value: ix + 1 } }));
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: 'Updated', title: Locale.detHistorySaved,
|
||||
value: Format.dtStr(this.record.updated) +
|
||||
(this.record.unsaved ? ' (current unsaved state)' : '') +
|
||||
((ix === this.history.length - 1 && !this.record.unsaved) ? ' (current state)' : '') } }));
|
||||
this.fieldViews.push(new FieldViewReadOnlyRaw({ model: { name: '$Title', title: 'Title',
|
||||
value: '<i class="fa fa-' + this.record.icon + ' ' + colorCls + '"></i> ' + _.escape(this.record.title) || '(no title)' } }));
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: '$UserName', title: 'User', value: this.record.user } }));
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: '$Password', title: 'Password', value: this.record.password } }));
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: '$URL', title: 'Website', value: this.record.url } }));
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: '$Notes', title: 'Notes', value: this.record.notes } }));
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: 'Tags', title: 'Tags', value: this.record.tags.join(', ') } }));
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: 'Expires', title: 'Expires',
|
||||
value: this.record.expires ? Format.dtStr(this.record.expires) : 'Never' } }));
|
||||
(this.record.unsaved ? ' (' + Locale.detHistoryCurUnsavedState + ')' : '') +
|
||||
((ix === this.history.length - 1 && !this.record.unsaved) ? ' (' + Locale.detHistoryCurState + ')' : '') } }));
|
||||
this.fieldViews.push(new FieldViewReadOnlyRaw({ model: { name: '$Title', title: Locale.detHistoryTitle,
|
||||
value: '<i class="fa fa-' + this.record.icon + ' ' + colorCls + '"></i> ' +
|
||||
_.escape(this.record.title) || '(' + Locale.detHistoryNoTitle + ')' } }));
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: '$UserName', title: Locale.detUser, value: this.record.user } }));
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: '$Password', title: Locale.detPassword, value: this.record.password } }));
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: '$URL', title: Locale.detWebsite, value: this.record.url } }));
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: '$Notes', title: Locale.detNotes, value: this.record.notes } }));
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: 'Tags', title: Locale.detTags, value: this.record.tags.join(', ') } }));
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: 'Expires', title: Locale.detExpires,
|
||||
value: this.record.expires ? Format.dtStr(this.record.expires) : '' } }));
|
||||
_.forEach(this.record.fields, function(value, field) {
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: '$' + field, title: field, value: value } }));
|
||||
}, this);
|
||||
if (this.record.attachments.length) {
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: 'Attachments', title: 'Attachments',
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: 'Attachments', title: Locale.detAttachments,
|
||||
value: this.record.attachments.map(function(att) { return att.title; }).join(', ') } }));
|
||||
}
|
||||
this.fieldViews.forEach(function(fieldView) {
|
||||
|
|
|
@ -18,6 +18,7 @@ var Backbone = require('backbone'),
|
|||
Alerts = require('../../comp/alerts'),
|
||||
CopyPaste = require('../../comp/copy-paste'),
|
||||
Format = require('../../util/format'),
|
||||
Locale = require('../../util/locale'),
|
||||
FileSaver = require('filesaver'),
|
||||
baron = require('baron'),
|
||||
kdbxweb = require('kdbxweb');
|
||||
|
@ -105,31 +106,31 @@ var DetailsView = Backbone.View.extend({
|
|||
|
||||
addFieldViews: function() {
|
||||
var model = this.model;
|
||||
this.fieldViews.push(new FieldViewText({ model: { name: '$UserName', title: 'User',
|
||||
this.fieldViews.push(new FieldViewText({ model: { name: '$UserName', title: Locale.detUser,
|
||||
value: function() { return model.user; } } }));
|
||||
this.fieldViews.push(new FieldViewText({ model: { name: '$Password', title: 'Password', canGen: true,
|
||||
this.fieldViews.push(new FieldViewText({ model: { name: '$Password', title: Locale.detPassword, canGen: true,
|
||||
value: function() { return model.password; } } }));
|
||||
this.fieldViews.push(new FieldViewUrl({ model: { name: '$URL', title: 'Website',
|
||||
this.fieldViews.push(new FieldViewUrl({ model: { name: '$URL', title: Locale.detWebsite,
|
||||
value: function() { return model.url; } } }));
|
||||
this.fieldViews.push(new FieldViewText({ model: { name: '$Notes', title: 'Notes', multiline: 'true',
|
||||
this.fieldViews.push(new FieldViewText({ model: { name: '$Notes', title: Locale.detNotes, multiline: 'true',
|
||||
value: function() { return model.notes; } } }));
|
||||
this.fieldViews.push(new FieldViewTags({ model: { name: 'Tags', title: 'Tags', tags: this.appModel.tags,
|
||||
this.fieldViews.push(new FieldViewTags({ model: { name: 'Tags', title: Locale.detTags, tags: this.appModel.tags,
|
||||
value: function() { return model.tags; } } }));
|
||||
this.fieldViews.push(new FieldViewDate({ model: { name: 'Expires', title: 'Expires', lessThanNow: '(expired)',
|
||||
this.fieldViews.push(new FieldViewDate({ model: { name: 'Expires', title: Locale.detExpires, lessThanNow: '(' + Locale.detExpired + ')',
|
||||
value: function() { return model.expires; } } }));
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: 'File', title: 'File',
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: 'File', title: Locale.detFile,
|
||||
value: function() { return model.fileName; } } }));
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: 'Created', title: 'Created',
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: 'Created', title: Locale.detCreated,
|
||||
value: function() { return Format.dtStr(model.created); } } }));
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: 'Updated', title: 'Updated',
|
||||
this.fieldViews.push(new FieldViewReadOnly({ model: { name: 'Updated', title: Locale.detUpdated,
|
||||
value: function() { return Format.dtStr(model.updated); } } }));
|
||||
this.fieldViews.push(new FieldViewHistory({ model: { name: 'History', title: 'History',
|
||||
this.fieldViews.push(new FieldViewHistory({ model: { name: 'History', title: Locale.detHistory,
|
||||
value: function() { return { length: model.historyLength, unsaved: model.unsaved }; } } }));
|
||||
_.forEach(model.fields, function(value, field) {
|
||||
this.fieldViews.push(new FieldViewCustom({ model: { name: '$' + field, title: field,
|
||||
value: function() { return model.fields[field]; } } }));
|
||||
}, this);
|
||||
var newFieldTitle = 'New Field';
|
||||
var newFieldTitle = Locale.detNetField;
|
||||
if (model.fields[newFieldTitle]) {
|
||||
for (var i = 1; ; i++) {
|
||||
var newFieldTitleVariant = newFieldTitle + i;
|
||||
|
@ -139,7 +140,7 @@ var DetailsView = Backbone.View.extend({
|
|||
}
|
||||
}
|
||||
}
|
||||
this.fieldViews.push(new FieldViewCustom({ model: { name: '', title: 'add field', newField: newFieldTitle,
|
||||
this.fieldViews.push(new FieldViewCustom({ model: { name: '', title: Locale.detAddField, newField: newFieldTitle,
|
||||
value: function() { return ''; } } }));
|
||||
|
||||
var fieldsMainEl = this.$el.find('.details__body-fields');
|
||||
|
@ -486,8 +487,8 @@ var DetailsView = Backbone.View.extend({
|
|||
|
||||
deleteFromTrash: function() {
|
||||
Alerts.yesno({
|
||||
header: 'Delete from trash?',
|
||||
body: 'You will not be able to put it back<p class="muted-color">To quickly remove all items from trash, click empty icon in Trash menu</p>',
|
||||
header: Locale.detDelFromTrash,
|
||||
body: Locale.detDelFromTrashBody + ' <p class="muted-color">' + Locale.detDelFromTrashBodyHint + '</p>',
|
||||
icon: 'minus-circle',
|
||||
success: (function() {
|
||||
this.model.deleteFromTrash();
|
||||
|
|
|
@ -30,9 +30,9 @@ var FieldViewDate = FieldViewText.extend({
|
|||
i18n: {
|
||||
previousMonth: '',
|
||||
nextMonth: '',
|
||||
months: Locale.Months,
|
||||
weekdays: Locale.Weekdays,
|
||||
weekdaysShort: Locale.WeekdaysShort
|
||||
months: Locale.months,
|
||||
weekdays: Locale.weekdays,
|
||||
weekdaysShort: Locale.weekdaysShort
|
||||
}
|
||||
});
|
||||
_.defer(this.picker.show.bind(this.picker));
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
'use strict';
|
||||
|
||||
var FieldView = require('./field-view');
|
||||
var FieldView = require('./field-view'),
|
||||
Locale = require('../../util/locale');
|
||||
|
||||
var FieldViewHistory = FieldView.extend({
|
||||
renderValue: function(value) {
|
||||
if (!value.length) {
|
||||
return 'empty';
|
||||
return Locale.detHistoryEmpty;
|
||||
}
|
||||
var text = value.length + ' record' + (value.length % 10 === 1 ? '' : 's');
|
||||
var text = value.length + ' ' + (value.length % 10 === 1 ? Locale.detHistoryRec : Locale.detHistoryRecs);
|
||||
if (value.unsaved) {
|
||||
text += ' (modified)';
|
||||
text += ' (' + Locale.detHistoryModified + ')';
|
||||
}
|
||||
return '<a class="details__history-link">' + text + '</a>';
|
||||
},
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
var Backbone = require('backbone'),
|
||||
PasswordGenerator = require('../util/password-generator'),
|
||||
CopyPaste = require('../comp/copy-paste');
|
||||
CopyPaste = require('../comp/copy-paste'),
|
||||
Locale = require('../util/locale');
|
||||
|
||||
var DefaultGenOpts = {
|
||||
length: 16, upper: true, lower: true, digits: true, special: false, brackets: false, high: false, ambiguous: false
|
||||
|
@ -31,7 +32,7 @@ var GeneratorView = Backbone.View.extend({
|
|||
|
||||
render: function() {
|
||||
var canCopy = document.queryCommandSupported('copy');
|
||||
var btnTitle = this.model.copy ? canCopy ? 'Copy' : 'Close' : 'OK';
|
||||
var btnTitle = this.model.copy ? canCopy ? Locale.alertCopy : Locale.alertClose : Locale.alertOk;
|
||||
this.renderTemplate({ btnTitle: btnTitle, opt: this.gen });
|
||||
this.resultEl = this.$el.find('.gen__result');
|
||||
this.$el.css(this.model.pos);
|
||||
|
|
|
@ -4,7 +4,8 @@ var Backbone = require('backbone'),
|
|||
Keys = require('../const/keys'),
|
||||
KeyHandler = require('../comp/key-handler'),
|
||||
DropdownView = require('./dropdown-view'),
|
||||
FeatureDetector = require('../util/feature-detector');
|
||||
FeatureDetector = require('../util/feature-detector'),
|
||||
Locale = require('../util/locale');
|
||||
|
||||
var ListSearchView = Backbone.View.extend({
|
||||
template: require('templates/list-search.hbs'),
|
||||
|
@ -28,24 +29,24 @@ var ListSearchView = Backbone.View.extend({
|
|||
|
||||
initialize: function () {
|
||||
this.sortOptions = [
|
||||
{ value: 'title', icon: 'sort-alpha-asc', text: 'Title A → Z' },
|
||||
{ value: '-title', icon: 'sort-alpha-desc', text: 'Title Z → A' },
|
||||
{ value: 'website', icon: 'sort-alpha-asc', text: 'Website A → Z' },
|
||||
{ value: '-website', icon: 'sort-alpha-desc', text: 'Website Z → A' },
|
||||
{ value: 'user', icon: 'sort-alpha-asc', text: 'User A → Z' },
|
||||
{ value: '-user', icon: 'sort-alpha-desc', text: 'User Z → A' },
|
||||
{ value: 'created', icon: 'sort-numeric-asc', text: 'Created Old → New' },
|
||||
{ value: '-created', icon: 'sort-numeric-desc', text: 'Created New → Old' },
|
||||
{ value: 'updated', icon: 'sort-numeric-asc', text: 'Updated Old → New' },
|
||||
{ value: '-updated', icon: 'sort-numeric-desc', text: 'Updated New → Old' },
|
||||
{ value: '-attachments', icon: 'sort-amount-desc', text: 'Attachments' }
|
||||
{ value: 'title', icon: 'sort-alpha-asc', text: Locale.searchTitle + ' ' + Locale.searchAZ },
|
||||
{ value: '-title', icon: 'sort-alpha-desc', text: Locale.searchTitle + ' ' + Locale.searchZA },
|
||||
{ value: 'website', icon: 'sort-alpha-asc', text: Locale.searchWebsite + ' ' + Locale.searchAZ },
|
||||
{ value: '-website', icon: 'sort-alpha-desc', text: Locale.searchWebsite + ' ' + Locale.searchZA },
|
||||
{ value: 'user', icon: 'sort-alpha-asc', text: Locale.searchUser + ' ' + Locale.searchAZ },
|
||||
{ value: '-user', icon: 'sort-alpha-desc', text: Locale.searchUser + ' ' + Locale.searchZA },
|
||||
{ value: 'created', icon: 'sort-numeric-asc', text: Locale.searchCreated + ' ' + Locale.searchON },
|
||||
{ value: '-created', icon: 'sort-numeric-desc', text: Locale.searchCreated + ' ' + Locale.searchNO },
|
||||
{ value: 'updated', icon: 'sort-numeric-asc', text: Locale.searchUpdated + ' ' + Locale.searchON },
|
||||
{ value: '-updated', icon: 'sort-numeric-desc', text: Locale.searchUpdated + ' ' + Locale.searchNO },
|
||||
{ value: '-attachments', icon: 'sort-amount-desc', text: Locale.searchAttachments }
|
||||
];
|
||||
this.sortIcons = {};
|
||||
this.sortOptions.forEach(function(opt) {
|
||||
this.sortIcons[opt.value] = opt.icon;
|
||||
}, this);
|
||||
this.createOptions = [
|
||||
{ value: 'entry', icon: 'key', text: 'Entry <span class="muted-color">(shift-click or ' +
|
||||
{ value: 'entry', icon: 'key', text: 'Entry <span class="muted-color">(' + Locale.searchShiftClickOr + ' ' +
|
||||
FeatureDetector.altShortcutSymbol(true) + 'N)</span>' },
|
||||
{ value: 'group', icon: 'folder', text: 'Group' }
|
||||
];
|
||||
|
|
|
@ -4,7 +4,8 @@ var Backbone = require('backbone'),
|
|||
KeyHandler = require('../../comp/key-handler'),
|
||||
Keys = require('../../const/keys'),
|
||||
Alerts = require('../../comp/alerts'),
|
||||
DragDropInfo = require('../../comp/drag-drop-info');
|
||||
DragDropInfo = require('../../comp/drag-drop-info'),
|
||||
Locale = require('../../util/locale');
|
||||
|
||||
var MenuItemView = Backbone.View.extend({
|
||||
template: require('templates/menu/menu-item.hbs'),
|
||||
|
@ -162,8 +163,8 @@ var MenuItemView = Backbone.View.extend({
|
|||
emptyTrash: function(e) {
|
||||
e.stopPropagation();
|
||||
Alerts.yesno({
|
||||
header: 'Empty trash?',
|
||||
body: 'You will not be able to put items back',
|
||||
header: Locale.menuEmptyTrashAlert,
|
||||
body: Locale.menuEmptyTrashAlertBody,
|
||||
icon: 'minus-circle',
|
||||
success: function() {
|
||||
Backbone.trigger('empty-trash');
|
||||
|
|
|
@ -5,7 +5,8 @@ var Backbone = require('backbone'),
|
|||
Alerts = require('../comp/alerts'),
|
||||
SecureInput = require('../comp/secure-input'),
|
||||
DropboxLink = require('../comp/dropbox-link'),
|
||||
Logger = require('../util/logger');
|
||||
Logger = require('../util/logger'),
|
||||
Locale = require('../util/locale');
|
||||
|
||||
var logger = new Logger('open-view');
|
||||
|
||||
|
@ -113,7 +114,7 @@ var OpenView = Backbone.View.extend({
|
|||
}
|
||||
}).bind(this);
|
||||
reader.onerror = (function() {
|
||||
Alerts.error({ header: 'Failed to read file' });
|
||||
Alerts.error({ header: Locale.openFailedRead });
|
||||
if (complete) {
|
||||
complete(false);
|
||||
}
|
||||
|
@ -125,7 +126,7 @@ var OpenView = Backbone.View.extend({
|
|||
this.$el.addClass('open--file');
|
||||
this.$el.find('.open__settings-key-file').removeClass('hide');
|
||||
this.inputEl[0].removeAttribute('readonly');
|
||||
this.inputEl[0].setAttribute('placeholder', 'Password for ' + this.params.name);
|
||||
this.inputEl[0].setAttribute('placeholder', Locale.openPassFor + ' ' + this.params.name);
|
||||
this.inputEl.focus();
|
||||
},
|
||||
|
||||
|
@ -290,16 +291,15 @@ var OpenView = Backbone.View.extend({
|
|||
});
|
||||
if (!buttons.length) {
|
||||
Alerts.error({
|
||||
header: 'Nothing found',
|
||||
body: 'You have no files in your Dropbox which could be opened.' +
|
||||
(dirStat && dirStat.inAppFolder ? ' Files are searched inside app folder in your Dropbox.' : '')
|
||||
header: Locale.openNothingFound,
|
||||
body: Locale.openNothingFoundBody + (dirStat && dirStat.inAppFolder ? ' ' + Locale.openNothingFoundBodyAppFolder : '')
|
||||
});
|
||||
return;
|
||||
}
|
||||
buttons.push({ result: '', title: 'Cancel' });
|
||||
buttons.push({ result: '', title: Locale.alertCancel });
|
||||
Alerts.alert({
|
||||
header: 'Select a file',
|
||||
body: 'Select a file from your Dropbox which you would like to open',
|
||||
header: Locale.openSelectFile,
|
||||
body: Locale.openSelectFileBody,
|
||||
icon: 'dropbox',
|
||||
buttons: buttons,
|
||||
esc: '',
|
||||
|
|
|
@ -9,6 +9,7 @@ var Backbone = require('backbone'),
|
|||
Links = require('../../const/links'),
|
||||
DropboxLink = require('../../comp/dropbox-link'),
|
||||
Format = require('../../util/format'),
|
||||
Locale = require('../../util/locale'),
|
||||
kdbxweb = require('kdbxweb'),
|
||||
FileSaver = require('filesaver');
|
||||
|
||||
|
@ -72,14 +73,15 @@ var SettingsAboutView = Backbone.View.extend({
|
|||
var sel = this.$el.find('#settings__file-key-file');
|
||||
sel.html('');
|
||||
if (keyFileName && keyFileChanged) {
|
||||
var text = keyFileName !== 'Generated' ? 'Use key file ' + keyFileName : 'Use generated key file';
|
||||
var text = keyFileName !== 'Generated' ? Locale.setFileUseKeyFile + ' ' + keyFileName : Locale.setFileUseGenKeyFile;
|
||||
$('<option/>').val('ex').text(text).appendTo(sel);
|
||||
}
|
||||
if (oldKeyFileName) {
|
||||
$('<option/>').val('old').text('Use ' + (keyFileChanged ? 'old ' : '') + 'key file ' + oldKeyFileName).appendTo(sel);
|
||||
var useText = keyFileChanged ? Locale.setFileUseOldKeyFile : Locale.setFileUseKeyFile + ' ' + oldKeyFileName;
|
||||
$('<option/>').val('old').text(useText).appendTo(sel);
|
||||
}
|
||||
$('<option/>').val('gen').text('Generate new key file').appendTo(sel);
|
||||
$('<option/>').val('none').text('Don\'t use key file').appendTo(sel);
|
||||
$('<option/>').val('gen').text(Locale.setFileGenKeyFile).appendTo(sel);
|
||||
$('<option/>').val('none').text(Locale.setFileDontUseKeyFile).appendTo(sel);
|
||||
if (keyFileName && keyFileChanged) {
|
||||
sel.val('ex');
|
||||
} else if (!keyFileName) {
|
||||
|
@ -93,8 +95,8 @@ var SettingsAboutView = Backbone.View.extend({
|
|||
if (!this.model.get('passwordLength')) {
|
||||
var that = this;
|
||||
Alerts.yesno({
|
||||
header: 'Empty password',
|
||||
body: 'Saving database with empty password makes it completely unprotected. Do you really want to do it?',
|
||||
header: Locale.setFileEmptyPass,
|
||||
body: Locale.setFileEmptyPassBody,
|
||||
success: function() {
|
||||
continueCallback();
|
||||
},
|
||||
|
@ -149,8 +151,8 @@ var SettingsAboutView = Backbone.View.extend({
|
|||
Storage.file.save(path, data, function (err) {
|
||||
if (err) {
|
||||
Alerts.error({
|
||||
header: 'Save error',
|
||||
body: 'Error saving to file ' + path + ': \n' + err
|
||||
header: Locale.setFileSaveError,
|
||||
body: Locale.setFileSaveErrorBody + ' ' + path + ': \n' + err
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -191,8 +193,8 @@ var SettingsAboutView = Backbone.View.extend({
|
|||
if (existingPath) {
|
||||
Alerts.yesno({
|
||||
icon: 'dropbox',
|
||||
header: 'Already exists',
|
||||
body: 'File ' + that.model.escape('name') + ' already exists in your Dropbox. Overwrite it?',
|
||||
header: Locale.setFileAlreadyExists,
|
||||
body: Locale.setFileAlreadyExistsBody.replace('{}', that.model.escape('name')),
|
||||
success: function() {
|
||||
that.model.set('syncing', true);
|
||||
DropboxLink.deleteFile(existingPath, function(err) {
|
||||
|
@ -215,12 +217,11 @@ var SettingsAboutView = Backbone.View.extend({
|
|||
if (this.model.get('modified')) {
|
||||
var that = this;
|
||||
Alerts.yesno({
|
||||
header: 'Unsaved changes',
|
||||
body: 'There are unsaved changes in this file',
|
||||
header: Locale.setFileUnsaved,
|
||||
body: Locale.setFileUnsavedBody,
|
||||
buttons: [
|
||||
//{result: 'save', title: 'Save and close'},
|
||||
{result: 'close', title: 'Close and lose changes', error: true},
|
||||
{result: '', title: 'Don\t close'}
|
||||
{result: 'close', title: Locale.setFileCloseNoSave, error: true},
|
||||
{result: '', title: Locale.setFileDontClose}
|
||||
],
|
||||
success: function(result) {
|
||||
if (result === 'close') {
|
||||
|
|
|
@ -8,6 +8,7 @@ var Backbone = require('backbone'),
|
|||
UpdateModel = require('../../models/update-model'),
|
||||
RuntimeInfo = require('../../comp/runtime-info'),
|
||||
FeatureDetector = require('../../util/feature-detector'),
|
||||
Locale = require('../../util/locale'),
|
||||
Links = require('../../const/links');
|
||||
|
||||
var SettingsGeneralView = Backbone.View.extend({
|
||||
|
@ -77,36 +78,36 @@ var SettingsGeneralView = Backbone.View.extend({
|
|||
getUpdateInfo: function() {
|
||||
switch (UpdateModel.instance.get('status')) {
|
||||
case 'checking':
|
||||
return 'Checking for updates...';
|
||||
return Locale.setGenUpdateChecking + '...';
|
||||
case 'error':
|
||||
var errMsg = 'Error checking for updates';
|
||||
var errMsg = Locale.setGenErrorChecking;
|
||||
if (UpdateModel.instance.get('lastError')) {
|
||||
errMsg += ': ' + UpdateModel.instance.get('lastError');
|
||||
}
|
||||
if (UpdateModel.instance.get('lastSuccessCheckDate')) {
|
||||
errMsg += '. Last successful check was at ' + Format.dtStr(UpdateModel.instance.get('lastSuccessCheckDate')) +
|
||||
': the latest version was ' + UpdateModel.instance.get('lastVersion');
|
||||
errMsg += '. ' + Locale.setGenLastCheckSuccess.replace('{}', Format.dtStr(UpdateModel.instance.get('lastSuccessCheckDate'))) +
|
||||
': ' + Locale.setGenLastCheckVer.replace('{}', UpdateModel.instance.get('lastVersion'));
|
||||
}
|
||||
return errMsg;
|
||||
case 'ok':
|
||||
var msg = 'Checked at ' + Format.dtStr(UpdateModel.instance.get('lastCheckDate')) + ': ';
|
||||
var msg = Locale.setGenCheckedAt + ' ' + Format.dtStr(UpdateModel.instance.get('lastCheckDate')) + ': ';
|
||||
if (RuntimeInfo.version === UpdateModel.instance.get('lastVersion')) {
|
||||
msg += 'you are using the latest version';
|
||||
msg += Locale.setGenLatestVer;
|
||||
} else {
|
||||
msg += 'new version ' + UpdateModel.instance.get('lastVersion') + ' available, released at ' +
|
||||
msg += Locale.setGenNewVer.replace('{}', UpdateModel.instance.get('lastVersion')) + ' ' +
|
||||
Format.dStr(UpdateModel.instance.get('lastVersionReleaseDate'));
|
||||
}
|
||||
switch (UpdateModel.instance.get('updateStatus')) {
|
||||
case 'downloading':
|
||||
return msg + '. Downloading update...';
|
||||
return msg + '. ' + Locale.setGenDownloadingUpdate;
|
||||
case 'extracting':
|
||||
return msg + '. Extracting update...';
|
||||
return msg + '. ' + Locale.setGenExtractingUpdate;
|
||||
case 'error':
|
||||
return msg + '. There was an error downloading new version';
|
||||
return msg + '. ' + Locale.setGenCheckErr;
|
||||
}
|
||||
return msg;
|
||||
default:
|
||||
return 'Never checked for updates';
|
||||
return Locale.setGenNeverChecked;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="details__attachment-preview">
|
||||
<div class="details__attachment-preview-data"></div>
|
||||
<i class="fa details__attachment-preview-icon"></i>
|
||||
<div class="details__attachment-preview-download-text">Shift-click attachment button to download
|
||||
or <span class="details__attachment-preview-download-text-shortcut"></span>Delete to remove</div>
|
||||
<div class="details__attachment-preview-download-text">{{res 'detAttDownload'}}
|
||||
<span class="details__attachment-preview-download-text-shortcut"></span>{{res 'detAttDelToRemove'}}</div>
|
||||
</div>
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
<div class="empty-block muted-color">
|
||||
<h1 class="empty-block__title">Your passwords will be displayed here</h1>
|
||||
</div>
|
||||
<h1 class="empty-block__title">{{res 'detEmpty'}}</h1>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="empty-block muted-color">
|
||||
<h1 class="empty-block__title">To restore this group, please drag it to any group outside trash</h1>
|
||||
<h1 class="empty-block__title">{{res 'detGroupRestore'}}</h1>
|
||||
<div class="empty-block__lower-btns">
|
||||
<i class="details__buttons-trash-del fa fa-minus-circle"></i>
|
||||
</div>
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
<div class="details__history">
|
||||
<div class="details__history-desc muted-color">Click entry history timeline point to view state</div>
|
||||
<div class="details__history-desc muted-color">{{res 'detHistoryClickPoint'}}</div>
|
||||
<div class="details__history-top">
|
||||
<div class="details__history-timeline">
|
||||
<div class="details__history-timeline-axis"></div>
|
||||
<div class="details__history-arrow-prev"><i class="fa fa-long-arrow-left"></i></div>
|
||||
<div class="details__history-arrow-next"><i class="fa fa-long-arrow-right"></i></div>
|
||||
</div>
|
||||
<a class="details__history-close">return to entry <i class="fa fa-external-link-square"></i></a>
|
||||
<a class="details__history-close">{{res 'detHistoryReturn'}} <i class="fa fa-external-link-square"></i></a>
|
||||
</div>
|
||||
<div class="details__history-body">
|
||||
<div class="details__field">
|
||||
<div class="details__field-label">Title</div>
|
||||
<div class="details__field-value"><i class="fa fa-key yellow-color"></i> Agent forum</div>
|
||||
<div class="details__field-label">{{Res 'title'}}</div>
|
||||
<div class="details__field-value"><i class="fa fa-key"></i> </div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="details__history-buttons">
|
||||
<button class="details__history-button details__history-button-revert btn-silent">Revert to state</button>
|
||||
<button class="details__history-button details__history-button-delete btn-error">Delete state</button>
|
||||
<button class="details__history-button details__history-button-discard btn-error">Discard changes</button>
|
||||
<button class="details__history-button details__history-button-revert btn-silent">{{res 'detHistoryRevert'}}</button>
|
||||
<button class="details__history-button details__history-button-delete btn-error">{{res 'detHistoryDel'}}</button>
|
||||
<button class="details__history-button details__history-button-discard btn-error">{{res 'detHistoryDiscard'}}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<div class="details">
|
||||
<div class="details__back-button">
|
||||
<i class="fa fa-chevron-left"></i> back to list
|
||||
<i class="fa fa-chevron-left"></i> {{res 'detBackToList'}}
|
||||
</div>
|
||||
<div class="details__header">
|
||||
<i class="details__header-color fa fa-bookmark-o" title="Change icon color">
|
||||
<i class="details__header-color fa fa-bookmark-o" title="{{res 'detSetIconColor'}}">
|
||||
<span class="details__colors-popup">
|
||||
<span class="details__colors-popup-item yellow-color fa fa-bookmark-o" data-color="yellow"></span>
|
||||
<span class="details__colors-popup-item green-color fa fa-bookmark-o" data-color="green"></span>
|
||||
|
@ -15,9 +15,9 @@
|
|||
</i>
|
||||
<h1 class="details__header-title">{{#if title}}{{title}}{{else}}(no title){{/if}}</h1>
|
||||
{{#if customIcon}}
|
||||
<div class="details__header-icon details__header-icon--icon" style="background-image: url({{{customIcon}}})" title="Change icon"></div>
|
||||
<div class="details__header-icon details__header-icon--icon" style="background-image: url({{{customIcon}}})" title="{{res 'detSetIcon'}}"></div>
|
||||
{{else}}
|
||||
<i class="details__header-icon fa fa-{{icon}}" title="Change icon"></i>
|
||||
<i class="details__header-icon fa fa-{{icon}}" title="{{res 'detSetIcon'}}"></i>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="details__body">
|
||||
|
@ -31,22 +31,22 @@
|
|||
</div>
|
||||
<div class="details__buttons">
|
||||
{{#if deleted~}}
|
||||
<i class="details__buttons-trash-del fa fa-minus-circle" title="Delete permanently"></i>
|
||||
<i class="details__buttons-trash-del fa fa-minus-circle" title="{{res 'detDelEntryPerm'}}"></i>
|
||||
{{~else~}}
|
||||
<i class="details__buttons-trash fa fa-trash-o" title="Delete"></i>
|
||||
<i class="details__buttons-trash fa fa-trash-o" title="{{res 'detDelEntry'}}"></i>
|
||||
{{~/if~}}
|
||||
<div class="details__attachments">
|
||||
{{#each attachments as |attachment ix|}}
|
||||
<div class="details__attachment" data-id="{{ix}}"><i class="fa fa-{{attachment.icon}}"></i> {{attachment.title}}</div>
|
||||
{{else}}
|
||||
<div class="details__attachment-add">
|
||||
<span class="details__attachment-add-title">drag attachments here</span> <i class="fa fa-paperclip"></i>
|
||||
<span class="details__attachment-add-title">{{res 'detDropAttachments'}}</span> <i class="fa fa-paperclip"></i>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="details__dropzone">
|
||||
<i class="fa fa-paperclip muted-color details__dropzone-icon"></i>
|
||||
<h1 class="muted-color details__dropzone-header">drop attachments here</h1>
|
||||
<h1 class="muted-color details__dropzone-header">{{res 'detDropAttachments'}}</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
{{~/if}}
|
||||
</div>
|
||||
{{/each}}
|
||||
<div class="footer__db footer__db--dimmed footer__db--expanded footer__db-open"><i class="fa fa-plus"></i> Open / New</div>
|
||||
<div class="footer__db footer__db--dimmed footer__db--expanded footer__db-open"><i class="fa fa-plus"></i> {{res 'footerOpen'}}</div>
|
||||
<div class="footer__btn footer__btn-help"><i class="fa fa-question"></i></div>
|
||||
<div class="footer__btn footer__btn-settings">
|
||||
{{#if updateAvailable}}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="gen">
|
||||
<div>Length: <span class="gen__length-range-val">{{opt.length}}</span></div>
|
||||
<div>{{res 'genLen'}}: <span class="gen__length-range-val">{{opt.length}}</span></div>
|
||||
<input type="range" class="gen__length-range" value="13" min="0" max="25" />
|
||||
<div>
|
||||
<div class="gen__check"><input type="checkbox" id="gen__check-upper"
|
||||
|
@ -17,6 +17,6 @@
|
|||
<div class="gen__check"><input type="checkbox" id="gen__check-ambiguous"
|
||||
data-id="ambiguous" {{#if opt.ambiguous}}checked{{/if}}><label for="gen__check-ambiguous">0Oo</label></div>
|
||||
</div>
|
||||
<div class="gen__result">password</div>
|
||||
<div class="gen__result"></div>
|
||||
<div class="gen__btn-wrap"><button class="gen__btn-ok">{{btnTitle}}</button></div>
|
||||
</div>
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
<div class="grp">
|
||||
<div class="grp__back-button">
|
||||
return to app <i class="fa fa-external-link-square"></i>
|
||||
{{res 'retToApp'}} <i class="fa fa-external-link-square"></i>
|
||||
</div>
|
||||
<div class="scroller">
|
||||
<h1>Group</h1>
|
||||
<h1>{{res 'grpTitle'}}</h1>
|
||||
<div class="grp__field">
|
||||
<label for="grp__field-title">Name:</label>
|
||||
<label for="grp__field-title">{{Res 'name'}}:</label>
|
||||
<input type="text" class="input-base" id="grp__field-title" value="{{title}}" size="50" maxlength="1024"
|
||||
required {{#if readonly}}readonly{{/if}} />
|
||||
</div>
|
||||
{{#unless readonly}}
|
||||
<div>
|
||||
<input type="checkbox" class="input-base" id="grp__check-search" {{#if enableSearching}}checked{{/if}} />
|
||||
<label for="grp__check-search">Enable searching entries in this group</label>
|
||||
<label for="grp__check-search">{{res 'grpSearch'}}</label>
|
||||
</div>
|
||||
{{/unless}}
|
||||
<label>Icon:</label>
|
||||
<label>{{Res 'icon'}}:</label>
|
||||
{{#if customIcon}}
|
||||
<img src="{{{customIcon}}}" class="grp__icon grp__icon--image" />
|
||||
{{else}}
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
<input type="file" class="icon-select__file-input hide-by-pos" accept="image/*" />
|
||||
{{#if canDownloadFavicon}}
|
||||
<span class="icon-select__icon icon-select__icon-btn icon-select__icon-download"
|
||||
data-val="special" data-special="download" title="Download and use website favicon">
|
||||
data-val="special" data-special="download" title="{{res 'iconFavTitle'}}">
|
||||
<i class="fa fa-cloud-download"></i>
|
||||
</span>
|
||||
{{/if}}
|
||||
<span class="icon-select__icon icon-select__icon-btn icon-select__icon-select"
|
||||
data-val="special" data-special="select" title="Select custom icon">
|
||||
data-val="special" data-special="select" title="{{res 'iconSelCustom'}}">
|
||||
<i class="fa fa-ellipsis-h"></i>
|
||||
</span>
|
||||
{{#each customIcons as |icon ci|}}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div class="empty-block muted-color">
|
||||
<div class="empty-block__icon"><i class="fa fa-key"></i></div>
|
||||
<h1 class="empty-block__title">Empty</h1>
|
||||
<h1 class="empty-block__title">{{res 'listEmptyTitle'}}</h1>
|
||||
<p class="empty-block__text">
|
||||
add with <i class="fa fa-plus"></i> button above
|
||||
{{#res 'listEmptyAdd'}} <i class="fa fa-plus"></i>{{/res}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -4,5 +4,5 @@
|
|||
{{~else~}}
|
||||
<i class="fa fa-{{icon}} {{#if color}}{{color}}-color{{/if}} list__item-icon"></i>
|
||||
{{~/if}}
|
||||
<span class="list__item-title">{{#if title}}{{title}}{{else}}(no title){{/if}}</span><span class="list__item-descr thin">{{description}}</span>
|
||||
<span class="list__item-title">{{#if title}}{{title}}{{else}}({{res 'noTitle'}}){{/if}}</span><span class="list__item-descr thin">{{description}}</span>
|
||||
</div>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<i class="fa fa-{{icon}} {{#if color}}{{color}}-color{{/if}} list__item-icon"></i>
|
||||
{{~/if~}}
|
||||
</td>
|
||||
<td>{{#if title}}{{title}}{{else}}(no title){{/if}}</td>
|
||||
<td>{{#if title}}{{title}}{{else}}({{res 'noTitle'}}){{/if}}</td>
|
||||
<td>{{user}}</td>
|
||||
<td>{{url}}</td>
|
||||
<td>{{tags}}</td>
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
<input type="text" class="list__search-field input-padding-right" autocomplete="off">
|
||||
<i class="list__search-icon-search fa fa-search"></i>
|
||||
</div>
|
||||
<div class="list__search-btn-new">
|
||||
<i class="fa fa-plus" title="Add new"></i>
|
||||
<div class="list__search-btn-new" title="{{res 'searchAddNew'}}">
|
||||
<i class="fa fa-plus"></i>
|
||||
</div>
|
||||
<div class="list__search-btn-sort">
|
||||
<i class="fa fa-sort-alpha-asc" title="Sort"></i>
|
||||
<div class="list__search-btn-sort" title="{{res 'searchSort'}}">
|
||||
<i class="fa fa-sort-alpha-asc"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Title</th>
|
||||
<th>User</th>
|
||||
<th>Website</th>
|
||||
<th>Tags</th>
|
||||
<th>Notes</th>
|
||||
<th>{{Res 'title'}}</th>
|
||||
<th>{{Res 'user'}}</th>
|
||||
<th>{{Res 'website'}}</th>
|
||||
<th>{{Res 'tags'}}</th>
|
||||
<th>{{Res 'notes'}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
{{~else~}}
|
||||
<i class="menu__item-icon fa {{#if icon}}fa-{{icon}}{{else}}menu__item-icon--no-icon{{/if}}"></i>
|
||||
{{~/if}}
|
||||
<span class="menu__item-title">{{#if title}}{{title}}{{else}}(no title){{/if}}</span>
|
||||
<span class="menu__item-title">{{#if title}}{{title}}{{else}}({{res 'noTitle'}}){{/if}}</span>
|
||||
{{#if options}}
|
||||
<div class="menu__item-options">
|
||||
{{#each options.models as |opt|}}
|
||||
|
@ -20,6 +20,6 @@
|
|||
</div>
|
||||
{{/if}}
|
||||
{{#if editable}}<i class="menu__item-edit fa fa-cog"></i>{{/if}}
|
||||
{{#ifeq filterKey 'trash'}}<i class="menu__item-empty-trash fa fa-minus-circle" title="Empty Trash"></i>{{/ifeq}}
|
||||
{{#ifeq filterKey 'trash'}}<i class="menu__item-empty-trash fa fa-minus-circle" title="{{res 'menuEmptyTrash'}}"></i>{{/ifeq}}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
<div class="open__icons">
|
||||
<div class="open__icon open__icon-open">
|
||||
<i class="fa fa-lock open__icon-i"></i>
|
||||
<div class="open__icon-text">Open</div>
|
||||
<div class="open__icon-text">{{res 'openOpen'}}</div>
|
||||
</div>
|
||||
<div class="open__icon open__icon-new">
|
||||
<i class="fa fa-plus open__icon-i"></i>
|
||||
<div class="open__icon-text">New</div>
|
||||
<div class="open__icon-text">{{res 'openNew'}}</div>
|
||||
</div>
|
||||
<div class="open__icon open__icon-dropbox">
|
||||
<i class="fa fa-dropbox open__icon-i"></i>
|
||||
|
@ -15,12 +15,12 @@
|
|||
</div>
|
||||
<div class="open__icon open__icon-demo">
|
||||
<i class="fa fa-magic open__icon-i"></i>
|
||||
<div class="open__icon-text">Demo</div>
|
||||
<div class="open__icon-text">{{res 'openDemo'}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="open__pass-area">
|
||||
<div class="open__pass-warn-wrap">
|
||||
<div class="open__pass-warning muted-color invisible"><i class="fa fa-exclamation-triangle"></i> Caps Lock is on</div>
|
||||
<div class="open__pass-warning muted-color invisible"><i class="fa fa-exclamation-triangle"></i> {{res 'openCaps'}}</div>
|
||||
</div>
|
||||
<div class="open__pass-field-wrap">
|
||||
<input class="open__pass-input" type="password" size="30" autocomplete="off" maxlength="128"
|
||||
|
@ -31,8 +31,8 @@
|
|||
<div class="open__settings">
|
||||
<div class="open__settings-key-file hide">
|
||||
<i class="fa fa-key open__settings-key-file-icon"></i>
|
||||
<span class="open__settings-key-file-name">key file</span>
|
||||
<span class="open__settings-key-file-dropbox"> (from dropbox)</span>
|
||||
<span class="open__settings-key-file-name">{{res 'openKeyFile'}}</span>
|
||||
<span class="open__settings-key-file-dropbox"> {{res 'openKeyFileDropbox'}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="open__last">
|
||||
|
@ -47,6 +47,6 @@
|
|||
</div>
|
||||
<div class="open__dropzone">
|
||||
<i class="fa fa-lock muted-color open__dropzone-icon"></i>
|
||||
<h1 class="muted-color open__dropzone-header">drop files here</h1>
|
||||
<h1 class="muted-color open__dropzone-header">{{res 'openDropHere'}}</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<div>
|
||||
<h1><i class="fa fa-info"></i> About KeeWeb v{{version}}</h1>
|
||||
<p>This is an open-source app created by <a href="http://antelle.net" target="_blank">Antelle</a> and licensed under
|
||||
<a href="{{licenseLink}}" target="_blank">MIT</a>.
|
||||
The source code and issues are <a href="{{repoLink}}" target="_blank">on GitHub <i class="fa fa-github-alt"></i></a>.</p>
|
||||
<p>This app is built with these awesome tools:</p>
|
||||
<h1><i class="fa fa-info"></i> {{res 'setAboutTitle'}} KeeWeb v{{version}}</h1>
|
||||
<p>{{#res 'setAboutFirst'}}<a href="http://antelle.net" target="_blank">Antelle</a>{{/res~}}
|
||||
{{~#res 'setAboutSecond'}}<a href="{{licenseLink}}" target="_blank">MIT</a>{{/res}}
|
||||
{{#res 'setAboutSource'}}<a href="{{repoLink}}" target="_blank">GitHub <i class="fa fa-github-alt"></i></a>{{/res}}</p>
|
||||
<p>{{res 'setAboutBuilt'}}:</p>
|
||||
<h3>Libraries</h3>
|
||||
<ul>
|
||||
<li><a href="http://electron.atom.io/" target="_blank">electron</a><span class="muted-color">, cross-platform desktop apps framework</span></li>
|
||||
|
@ -54,8 +54,8 @@
|
|||
and CSS toolkit</span></li>
|
||||
</ul>
|
||||
|
||||
<h2>License</h2>
|
||||
<p>The app itself and all included components which are not in public domain are licensed under MIT license:</p>
|
||||
<h2>{{res 'setAboutLic'}}</h2>
|
||||
<p>{{res 'setAboutLicComment'}}:</p>
|
||||
<p></p>
|
||||
<p>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
||||
|
|
|
@ -1,59 +1,59 @@
|
|||
<div>
|
||||
<h1><i class="fa fa-lock"></i> {{name}}</h1>
|
||||
{{#if storage}}
|
||||
{{#ifeq storage 'file'}}<p>File path: {{path}}</p>{{/ifeq}}
|
||||
{{#ifeq storage 'dropbox'}}<p>This file is opened from Dropbox.</p>{{/ifeq}}
|
||||
{{#ifeq storage 'file'}}<p>{{res 'setFilePath'}}: {{path}}</p>{{/ifeq}}
|
||||
{{#ifeq storage 'dropbox'}}<p>{{#res 'setFileStorage'}}Dropbox{{/res}}</p>{{/ifeq}}
|
||||
{{else}}
|
||||
<p>This file is stored in internal app storage.</p>
|
||||
<p>{{res 'setFileIntl'}}.</p>
|
||||
{{#unless supportFiles}}
|
||||
<p>Want to work seamlessly with local files? <a href="{{desktopLink}}" target="_blank">Download a desktop app</a></p>
|
||||
<p>{{res 'setFileLocalHint'}} <a href="{{desktopLink}}" target="_blank">{{res 'setFileDownloadApp'}}</a></p>
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
|
||||
<div class="settings__file-buttons">
|
||||
{{#ifemptyoreq storage 'file'}}<button class="settings__file-button-save-default">Save</button>{{/ifemptyoreq}}
|
||||
{{#ifemptyoreq storage 'file'}}<button class="settings__file-button-save-default">{{res 'setFileSave'}}</button>{{/ifemptyoreq}}
|
||||
<button class="settings__file-button-save-dropbox {{#ifneq storage 'dropbox'}}btn-silent{{/ifneq}}"
|
||||
{{#if syncing}}disabled{{/if}}>Sync with Dropbox</button>
|
||||
{{#ifneq storage 'file'}}<button class="settings__file-button-save-file btn-silent">Save to file</button>{{/ifneq}}
|
||||
<button class="settings__file-button-export-xml btn-silent">Export to XML</button>
|
||||
<button class="settings__file-button-close btn-silent">Close</button>
|
||||
{{#if syncing}}disabled{{/if}}>{{#res 'setFileSyncWith'}}Dropbox{{/res}}</button>
|
||||
{{#ifneq storage 'file'}}<button class="settings__file-button-save-file btn-silent">{{res 'setFileSaveFile'}}</button>{{/ifneq}}
|
||||
<button class="settings__file-button-export-xml btn-silent">{{res 'setFileExportXml'}}</button>
|
||||
<button class="settings__file-button-close btn-silent">{{res 'setFileClose'}}</button>
|
||||
</div>
|
||||
|
||||
{{#if storage}}
|
||||
<h2>Sync</h2>
|
||||
<div>Last sync: {{#if syncDate}}{{syncDate}}{{else}}unknown{{/if}} {{#if syncing}}(sync in progress...){{/if}}</div>
|
||||
{{#if syncError}}<div>Sync error: {{syncError}}</div>{{/if}}
|
||||
<h2>{{res 'setFileSync'}}</h2>
|
||||
<div>{{res 'setFileLastSync'}}: {{#if syncDate}}{{syncDate}}{{else}}{{res 'setFileLastSyncUnknown'}}{{/if}} {{#if syncing}}({{res 'setFileSyncInProgress'}}...){{/if}}</div>
|
||||
{{#if syncError}}<div>{{res 'setFileSyncError'}}: {{syncError}}</div>{{/if}}
|
||||
{{/if}}
|
||||
|
||||
<h2>Settings</h2>
|
||||
<label for="settings__file-master-pass" class="settings__file-master-pass-label input-base">Master password:
|
||||
<h2>{{res 'setFileSettings'}}</h2>
|
||||
<label for="settings__file-master-pass" class="settings__file-master-pass-label input-base">{{res 'setFilePass'}}:
|
||||
<span class="settings__file-master-pass-warning">
|
||||
<i class="fa fa-warning"></i> password was changed; leave the field blank to use old password
|
||||
<i class="fa fa-warning"></i> {{res 'setFilePassChanged'}}
|
||||
</span>
|
||||
</label>
|
||||
<input type="password" class="settings__input input-base" id="settings__file-master-pass" value="{{password}}" />
|
||||
<label for="settings__file-key-file">Key file:</label>
|
||||
<label for="settings__file-key-file">{{res 'setFileKeyFile'}}:</label>
|
||||
<select class="settings__select settings__select-no-margin input-base" id="settings__file-key-file"></select>
|
||||
<a id="settings__file-file-select-link">Select a key file</a>
|
||||
<a id="settings__file-file-select-link">{{res 'setFileSelKeyFile'}}</a>
|
||||
<input type="file" id="settings__file-file-select" class="hide-by-pos" />
|
||||
|
||||
<h2>Names</h2>
|
||||
<label for="settings__file-name">Name:</label>
|
||||
<h2>{{res 'setFileNames'}}</h2>
|
||||
<label for="settings__file-name">{{res 'setFileName'}}:</label>
|
||||
<input type="text" class="settings__input input-base" id="settings__file-name" value="{{name}}" required />
|
||||
<label for="settings__file-def-user">Default username:</label>
|
||||
<label for="settings__file-def-user">{{res 'setFileDefUser'}}:</label>
|
||||
<input type="text" class="settings__input input-base" id="settings__file-def-user" value="{{defaultUser}}" />
|
||||
|
||||
<h2>History</h2>
|
||||
<h2>{{res 'setFileHistory'}}</h2>
|
||||
<div>
|
||||
<input type="checkbox" class="settings__input input-base" id="settings__file-trash" {{#if recycleBinEnabled}}checked{{/if}}> />
|
||||
<label for="settings__file-trash">Enable trash</label>
|
||||
<input type="checkbox" class="settings__input input-base" id="settings__file-trash" {{#if recycleBinEnabled}}checked{{/if}} />
|
||||
<label for="settings__file-trash">{{res 'setFileEnableTrash'}}</label>
|
||||
</div>
|
||||
<label for="settings__file-hist-len">History length, keep last records per entry:</label>
|
||||
<label for="settings__file-hist-len">{{res 'setFileHistLen'}}:</label>
|
||||
<input type="text" pattern="\d+" required class="settings__input input-base" id="settings__file-hist-len" value="{{historyMaxItems}}" />
|
||||
<label for="settings__file-hist-size">History size, total MB per file:</label>
|
||||
<label for="settings__file-hist-size">{{res 'resFileHistSize'}}:</label>
|
||||
<input type="text" pattern="\d+" required class="settings__input input-base" id="settings__file-hist-size" value="{{historyMaxSize}}" />
|
||||
|
||||
<h2>Advanced</h2>
|
||||
<label for="settings__file-key-rounds">Key encryption rounds:</label>
|
||||
<h2>{{res 'setFileAdvanced'}}</h2>
|
||||
<label for="settings__file-key-rounds">{{res 'setFileRounds'}}:</label>
|
||||
<input type="text" pattern="\d+" required class="settings__input input-base" id="settings__file-key-rounds" value="{{keyEncryptionRounds}}" />
|
||||
</div>
|
||||
|
|
|
@ -1,45 +1,44 @@
|
|||
<div>
|
||||
<h1><i class="fa fa-cog"></i> General Settings</h1>
|
||||
<h1><i class="fa fa-cog"></i> {{res 'setGenTitle'}}</h1>
|
||||
|
||||
{{#if updateWaitingReload}}
|
||||
<h2 class="action-color">Update</h2>
|
||||
<div>New app version was released and downloaded. <a href="{{releaseNotesLink}}" target="_blank">View release notes</a></div>
|
||||
<h2 class="action-color">{{res 'setGenUpdate'}}</h2>
|
||||
<div>{{res 'setGenNewVersion'}}. <a href="{{releaseNotesLink}}" target="_blank">{{res 'setGenReleaseNotes'}}</a></div>
|
||||
<div class="settings__general-update-buttons">
|
||||
<button class="settings__general-restart-btn">Reload to update</button>
|
||||
<button class="settings__general-restart-btn">{{res 'setGenReloadToUpdate'}}</button>
|
||||
</div>
|
||||
{{else if updateManual}}
|
||||
<h2 class="action-color">Update</h2>
|
||||
<div>New version has been released. It will check for updates and install them automatically
|
||||
but auto-upgrading from your version is impossible.</div>
|
||||
<h2 class="action-color">{{res 'setGenUpdate'}}</h2>
|
||||
<div>{{res 'setGenUpdateManual'}}</div>
|
||||
<div class="settings__general-update-buttons">
|
||||
<button class="settings__general-download-update-btn">Download update</button>
|
||||
<button class="settings__general-download-update-btn">{{res 'setGenDownloadUpdate'}}</button>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if showUpdateBlock}}
|
||||
<h2>Update</h2>
|
||||
<h2>{{res 'setGenUpdate'}}</h2>
|
||||
<div>
|
||||
<select class="settings__general-auto-update settings__select input-base">
|
||||
<option value="install" {{#ifeq autoUpdate 'install'}}selected{{/ifeq}}>Download and install automatically</option>
|
||||
<option value="check" {{#ifeq autoUpdate 'check'}}selected{{/ifeq}}>Check but don't install</option>
|
||||
<option value="" {{#unless autoUpdate}}selected{{/unless}}>Never check for updates</option>
|
||||
<option value="install" {{#ifeq autoUpdate 'install'}}selected{{/ifeq}}>{{res 'setGenUpdateAuto'}}</option>
|
||||
<option value="check" {{#ifeq autoUpdate 'check'}}selected{{/ifeq}}>{{res 'setGenUpdateCheck'}}</option>
|
||||
<option value="" {{#unless autoUpdate}}selected{{/unless}}>{{res 'setGenNoUpdate'}}</option>
|
||||
</select>
|
||||
<div>{{updateInfo}}</div>
|
||||
<a href="{{releaseNotesLink}}" target="_blank">View release notes</a>
|
||||
<a href="{{releaseNotesLink}}" target="_blank">{{res 'setGenReleaseNotes'}}</a>
|
||||
</div>
|
||||
<div class="settings__general-update-buttons">
|
||||
{{#if updateInProgress}}
|
||||
<button class="settings__general-update-btn btn-silent" disabled>Checking for updates</button>
|
||||
<button class="settings__general-update-btn btn-silent" disabled>{{res 'setGenUpdateChecking'}}</button>
|
||||
{{else}}
|
||||
<button class="settings__general-update-btn btn-silent">Check for updates</button>
|
||||
<button class="settings__general-update-btn btn-silent">{{res 'setGenCheckUpdate'}}</button>
|
||||
{{/if}}
|
||||
{{#if updateReady}}<button class="settings__general-restart-btn">Restart to update</button>{{/if}}
|
||||
{{#if updateFound}}<button class="settings__general-update-found-btn">Download update and restart</button>{{/if}}
|
||||
{{#if updateReady}}<button class="settings__general-restart-btn">{{res 'setGenRestartToUpdate'}}</button>{{/if}}
|
||||
{{#if updateFound}}<button class="settings__general-update-found-btn">{{res 'setGenDownloadAndRestart'}}</button>{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<h2>Appearance</h2>
|
||||
<h2>{{res 'setGenAppearance'}}</h2>
|
||||
<div>
|
||||
<label for="settings__general-theme">Theme:</label>
|
||||
<label for="settings__general-theme">{{res 'setGenTheme'}}:</label>
|
||||
<select class="settings__general-theme settings__select input-base" id="settings__general-theme">
|
||||
{{#each themes as |name key|}}
|
||||
<option value="{{key}}" {{#ifeq key activeTheme}}selected{{/ifeq}}>{{name}}</option>
|
||||
|
@ -48,44 +47,44 @@
|
|||
</div>
|
||||
<div>
|
||||
<input type="checkbox" class="settings__input input-base settings__general-expand" id="settings__general-expand" {{#if expandGroups}}checked{{/if}} />
|
||||
<label for="settings__general-expand">Show entries from all subgroups</label>
|
||||
<label for="settings__general-expand">{{res 'setGenShowSubgroups'}}</label>
|
||||
</div>
|
||||
{{#if canSetTableView}}
|
||||
<div>
|
||||
<input type="checkbox" class="settings__input input-base settings__general-table-view" id="settings__general-table-view" {{#if tableView}}checked{{/if}} />
|
||||
<label for="settings__general-table-view">Entries list table view</label>
|
||||
<label for="settings__general-table-view">{{res 'setGenTableView'}}</label>
|
||||
</div>
|
||||
{{/if}}
|
||||
<div>
|
||||
<input type="checkbox" class="settings__input input-base settings__general-colorful-icons" id="settings__general-colorful-icons" {{#if colorfulIcons}}checked{{/if}} />
|
||||
<label for="settings__general-colorful-icons">Colorful custom icons in list</label>
|
||||
<label for="settings__general-colorful-icons">{{res 'setGenColorfulIcons'}}</label>
|
||||
</div>
|
||||
|
||||
<h2>Function</h2>
|
||||
<div>
|
||||
<input type="checkbox" class="settings__input input-base settings__general-auto-save" id="settings__general-auto-save"
|
||||
{{#if autoSave}}checked{{/if}} />
|
||||
<label for="settings__general-auto-save">Automatically save and sync</label>
|
||||
<label for="settings__general-auto-save">{{res 'setGenAutoSync'}}</label>
|
||||
</div>
|
||||
<div>
|
||||
<label for="settings__general-idle-minutes">Auto-lock if the app is inactive:</label>
|
||||
<label for="settings__general-idle-minutes">{{res 'setGenLockInactive'}}:</label>
|
||||
<select class="settings__general-idle-minutes settings__select input-base" id="settings__general-idle-minutes">
|
||||
<option value="0" {{#cmp idleMinutes 0 '<='}}selected{{/cmp}}>Don't auto-lock</option>
|
||||
<option value="5" {{#ifeq idleMinutes 5}}selected{{/ifeq}}>In 5 minutes</option>
|
||||
<option value="10" {{#ifeq idleMinutes 10}}selected{{/ifeq}}>In 10 minutes</option>
|
||||
<option value="15" {{#ifeq idleMinutes 15}}selected{{/ifeq}}>In 15 minutes</option>
|
||||
<option value="60" {{#ifeq idleMinutes 60}}selected{{/ifeq}}>In an hour</option>
|
||||
<option value="0" {{#cmp idleMinutes 0 '<='}}selected{{/cmp}}>{{res 'setGenNoAutoLock'}}</option>
|
||||
<option value="5" {{#ifeq idleMinutes 5}}selected{{/ifeq}}>{{#res 'setGenLockMinutes'}}5{{/res}}</option>
|
||||
<option value="10" {{#ifeq idleMinutes 10}}selected{{/ifeq}}>{{#res 'setGenLockMinutes'}}10{{/res}}</option>
|
||||
<option value="15" {{#ifeq idleMinutes 15}}selected{{/ifeq}}>{{#res 'setGenLockMinutes'}}15{{/res}}</option>
|
||||
<option value="60" {{#ifeq idleMinutes 60}}selected{{/ifeq}}>{{res 'setGenLockHour'}}</option>
|
||||
</select>
|
||||
</div>
|
||||
{{#if canClearClipboard}}
|
||||
<div>
|
||||
<label for="settings__general-clipboard">Clear clipboard after copy:</label>
|
||||
<label for="settings__general-clipboard">{{res 'setGenClearClip'}}:</label>
|
||||
<select class="settings__general-clipboard settings__select input-base" id="settings__general-clipboard">
|
||||
<option value="0" {{#unless clipboardSeconds}}selected{{/unless}}>Don't clear</option>
|
||||
<option value="5" {{#ifeq clipboardSeconds 5}}selected{{/ifeq}}>In 5 seconds</option>
|
||||
<option value="10" {{#ifeq clipboardSeconds 10}}selected{{/ifeq}}>In 10 seconds</option>
|
||||
<option value="15" {{#ifeq clipboardSeconds 15}}selected{{/ifeq}}>In 15 seconds</option>
|
||||
<option value="60" {{#ifeq clipboardSeconds 60}}selected{{/ifeq}}>In a minute</option>
|
||||
<option value="0" {{#unless clipboardSeconds}}selected{{/unless}}>{{res 'setGenNoClear'}}</option>
|
||||
<option value="5" {{#ifeq clipboardSeconds 5}}selected{{/ifeq}}>{{#res 'setGenClearSeconds'}}5{{/res}}</option>
|
||||
<option value="10" {{#ifeq clipboardSeconds 10}}selected{{/ifeq}}>{{#res 'setGenClearSeconds'}}10{{/res}}</option>
|
||||
<option value="15" {{#ifeq clipboardSeconds 15}}selected{{/ifeq}}>{{#res 'setGenClearSeconds'}}15{{/res}}</option>
|
||||
<option value="60" {{#ifeq clipboardSeconds 60}}selected{{/ifeq}}>{{res 'setGenClearMinute'}}</option>
|
||||
</select>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
@ -93,17 +92,17 @@
|
|||
<div>
|
||||
<input type="checkbox" class="settings__input input-base settings__general-minimize" id="settings__general-minimize"
|
||||
{{#if minimizeOnClose}}checked{{/if}} />
|
||||
<label for="settings__general-minimize">Minimize app instead of close</label>
|
||||
<label for="settings__general-minimize">{{res 'setGenMinInstead'}}</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="checkbox" class="settings__input input-base settings__general-lock-on-minimize" id="settings__general-lock-on-minimize"
|
||||
{{#if lockOnMinimize}}checked{{/if}} />
|
||||
<label for="settings__general-lock-on-minimize">Auto-lock on minimize</label>
|
||||
<label for="settings__general-lock-on-minimize">{{res 'setGenLockMinimize'}}</label>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if devTools}}
|
||||
<h2>Advanced</h2>
|
||||
<a class="settings__general-dev-tools-link">Show dev tools</a>
|
||||
<h2>{{res 'setGenAdvanced'}}</h2>
|
||||
<a class="settings__general-dev-tools-link">{{res 'setGenDevTools'}}</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
|
|
@ -1,23 +1,20 @@
|
|||
<div>
|
||||
<h1><i class="fa fa-question"></i> Help</h1>
|
||||
<h2>File Format</h2>
|
||||
<p>This is a port of <a href="http://keepass.info/" target="_blank">KeePass</a> app built with web technologies.
|
||||
It understands files in KeePass format (kdbx). You can create such files (password databases) either in KeePass, or in this app.
|
||||
The file format is 100% compatible and should be understood by both apps.
|
||||
<h1><i class="fa fa-question"></i> {{res 'setHelpTitle'}}</h1>
|
||||
<h2>{{res 'setHelpFormat'}}</h2>
|
||||
<p>{{#res 'setHelpFormatBody'}}<a href="http://keepass.info/" target="_blank">KeePass</a>{{/res}}</p>
|
||||
<h2>{{res 'setHelpProblems'}}</h2>
|
||||
<p>{{#res 'setHelpProblems1'}}<a href="{{issueLink}}" target="_blank">{{res 'setHelpOpenIssue'}}</a>{{/res}}
|
||||
{{#res 'setHelpProblems2'}}<a href="http://antelle.net/" target="_blank">{{res 'setHelpContactLink'}}</a>{{/res}}.
|
||||
</p>
|
||||
<h2>Problems?</h2>
|
||||
<p>If something goes wrong, please, <a href="{{issueLink}}" target="_blank">open an issue on GitHub</a>
|
||||
or <a href="http://antelle.net/" target="_blank">contact a developer</a> directly.
|
||||
</p>
|
||||
<p>App information:</p>
|
||||
<p>{{res 'setHelpAppInfo'}}:</p>
|
||||
<pre class="settings__pre input-base">{{appInfo}}</pre>
|
||||
<h2>Other platforms</h2>
|
||||
<h2>{{res 'setHelpOtherPlatforms'}}</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<i class="fa fa-windows"></i>
|
||||
<i class="fa fa-apple"></i>
|
||||
<i class="fa fa-linux"></i>
|
||||
<a href="{{desktopLink}}" target="_blank">Desktop apps</a>
|
||||
<a href="{{desktopLink}}" target="_blank">{{res 'setHelpDesktopApps'}}</a>
|
||||
</li>
|
||||
<li>
|
||||
<i class="fa fa-chrome"></i>
|
||||
|
@ -25,9 +22,9 @@
|
|||
<i class="fa fa-opera"></i>
|
||||
<i class="fa fa-compass"></i>
|
||||
<i class="fa fa-internet-explorer"></i>
|
||||
<a href="{{webAppLink}}" target="_blank">Web app</a>
|
||||
<a href="{{webAppLink}}" target="_blank">{{res 'setHelpWebApp'}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h2>Updates <i class="fa fa-twitter"></i></h2>
|
||||
<p>App twitter: <a href="https://twitter.com/kee_web" target="_blank">kee_web</a></p>
|
||||
<h2>{{res 'setHelpUpdates'}} <i class="fa fa-twitter"></i></h2>
|
||||
<p>{{res 'setHelpTwitter'}}: <a href="https://twitter.com/kee_web" target="_blank">kee_web</a></p>
|
||||
</div>
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
<div>
|
||||
<h1><i class="fa fa-keyboard-o"></i> Shortcuts</h1>
|
||||
<div><span class="shortcut">{{{cmd}}}A</span> or <span class="shortcut">{{{alt}}}A</span> show all items</div>
|
||||
<div><span class="shortcut">{{{alt}}}C</span> show items with colors</div>
|
||||
<div><span class="shortcut">{{{alt}}}D</span> go to trash</div>
|
||||
<div><span class="shortcut">{{{cmd}}}F</span> search, or just start typing</div>
|
||||
<div><span class="shortcut">esc</span> clear search</div>
|
||||
<div><span class="shortcut">⏎</span> go to entry</div>
|
||||
<div><span class="shortcut">{{{cmd}}}C</span> copy password or selected field</div>
|
||||
<div><span class="shortcut">↑</span> go to previous item</div>
|
||||
<div><span class="shortcut">↓</span> go to next item</div>
|
||||
<div><span class="shortcut">{{{alt}}}N</span> create entry</div>
|
||||
<div><span class="shortcut">{{{cmd}}}O</span> open / new</div>
|
||||
<div><span class="shortcut">{{{cmd}}}S</span> save</div>
|
||||
<div><span class="shortcut">{{{cmd}}}G</span> generate</div>
|
||||
<h1><i class="fa fa-keyboard-o"></i> {{res 'setShTitle'}}</h1>
|
||||
<div><span class="shortcut">{{{cmd}}}A</span> {{res 'or'}} <span class="shortcut">{{{alt}}}A</span> {{res 'setShShowAll'}}</div>
|
||||
<div><span class="shortcut">{{{alt}}}C</span> {{res 'setShColors'}}</div>
|
||||
<div><span class="shortcut">{{{alt}}}D</span> {{res 'setShTrash'}}</div>
|
||||
<div><span class="shortcut">{{{cmd}}}F</span> {{res 'setShFind'}}</div>
|
||||
<div><span class="shortcut">esc</span> {{res 'setShClearSearch'}}</div>
|
||||
<div><span class="shortcut">⏎</span> {{res 'setShEntry'}}</div>
|
||||
<div><span class="shortcut">{{{cmd}}}C</span> {{res 'setShCopy'}}</div>
|
||||
<div><span class="shortcut">↑</span> {{res 'setShPrev'}}</div>
|
||||
<div><span class="shortcut">↓</span> {{res 'setShNext'}}</div>
|
||||
<div><span class="shortcut">{{{alt}}}N</span> {{res 'setShCreateEntry'}}</div>
|
||||
<div><span class="shortcut">{{{cmd}}}O</span> {{res 'setShOpen'}}</div>
|
||||
<div><span class="shortcut">{{{cmd}}}S</span> {{res 'setShSave'}}</div>
|
||||
<div><span class="shortcut">{{{cmd}}}G</span> {{res 'setShGen'}}</div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="settings">
|
||||
<div class="settings__back-button">
|
||||
<i class="fa fa-chevron-left settings__back-button-pre"></i> return to app <i class="fa fa-external-link-square settings__back-button-post"></i>
|
||||
<i class="fa fa-chevron-left settings__back-button-pre"></i> {{res 'retToApp'}} <i class="fa fa-external-link-square settings__back-button-post"></i>
|
||||
</div>
|
||||
<div class="scroller">
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue