added missing i18n strings (#1)

This commit is contained in:
Kyle Spearrin 2016-11-19 01:36:09 -05:00
parent 1968dd2d08
commit e7e4a66750
26 changed files with 262 additions and 92 deletions

View File

@ -442,5 +442,165 @@
"security": {
"message": "Security",
"description": "Security"
},
"errorsOccurred": {
"message": "Errors have occurred",
"description": "Errors have occurred"
},
"emailRequired": {
"message": "Email address is required.",
"description": "Email address is required."
},
"invalidEmail": {
"message": "Invalid email address.",
"description": "Invalid email address."
},
"masterPassRequired": {
"message": "Master password is required.",
"description": "Master password is required."
},
"masterPassLength": {
"message": "Master password must be at least 8 characters long.",
"description": "Master password must be at least 8 characters long."
},
"masterPassDoesntMatch": {
"message": "Master password confirmation does not match.",
"description": "Master password confirmation does not match."
},
"newAccountCreated": {
"message": "Your new account has been created! You may now log in.",
"description": "Your new account has been created! You may now log in."
},
"masterPassSent": {
"message": "We've sent you an email with your master password hint.",
"description": "We've sent you an email with your master password hint."
},
"verificationCodeRequired": {
"message": "Verification code is required.",
"description": "Verification code is required."
},
"valueCopied": {
"message": " copied",
"description": "' copied'. This is part of a sentence to be sure to leave the space prefix. For example: 'Password copied'"
},
"autofillError": {
"message": "Unable to auto-fill the selected site on this page. Copy/paste your username and/or password instead.",
"description": "Errors have occurred"
},
"loggedOut": {
"message": "Logged out",
"description": "Logged out"
},
"loginExpired": {
"message": "Your login session has expired.",
"description": "Your login session has expired."
},
"logOutConfirmation": {
"message": "Are you sure you want to log out?",
"description": "Are you sure you want to log out?"
},
"yes": {
"message": "Yes",
"description": "Yes"
},
"no": {
"message": "No",
"description": "No"
},
"unexpectedError": {
"message": "An unexpected error has occured.",
"description": "An unexpected error has occured."
},
"nameRequired": {
"message": "Name is required.",
"description": "Name is required."
},
"addedFolder": {
"message": "Added folder",
"description": "Added folder"
},
"changeMasterPass": {
"message": "Change Master Password",
"description": "Change Master Password"
},
"changeMasterPasswordConfirmation": {
"message": "You can change your master password on the bitwarden.com web vault. Do you want to visit the website now?",
"description": "You can change your master password on the bitwarden.com web vault. Do you want to visit the website now?"
},
"changeEmailConfirmation": {
"message": "You can change your email address on the bitwarden.com web vault. Do you want to visit the website now?",
"description": "You can change your email address on the bitwarden.com web vault. Do you want to visit the website now?"
},
"twoStepLoginConfirmation": {
"message": "Two-step login makes your account more secure by requiring you to enter a security code from an authenticator app whenever you log in. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?",
"description": "Two-step login makes your account more secure by requiring you to enter a security code from an authenticator app whenever you log in. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?"
},
"loggingOut": {
"message": "Logging out",
"description": "Logging out"
},
"loggingOutConfirmation": {
"message": "You've recently updated from an older version. You must re-log in to change your lock options. Do you want to log out now?",
"description": "You've recently updated from an older version. You must re-log in to change your lock options. Do you want to log out now?"
},
"editedFolder": {
"message": "Edited Folder",
"description": "Edited Folder"
},
"deleteFolderConfirmation": {
"message": "Are you sure you want to delete this folder?",
"description": "Are you sure you want to delete this folder?"
},
"deletedFolder": {
"message": "Deleted folder",
"description": "Deleted folder"
},
"gettingStartedTutorial": {
"message": "Getting Started Tutorial",
"description": "Getting Started Tutorial"
},
"gettingStartedTutorialVideo": {
"message": "Watch our getting started tutorial to learn how to get the most out of the browser extension.",
"description": "Watch our getting started tutorial to learn how to get the most out of the browser extension."
},
"syncingComplete": {
"message": "Syncing complete",
"description": "Syncing complete"
},
"importLoginsConfirmation": {
"message": "You can bulk import logins from the bitwarden.com web vault. Do you want to visit the website now?",
"description": "You can bulk import logins from the bitwarden.com web vault. Do you want to visit the website now?"
},
"passwordCopied": {
"message": "Password copied",
"description": "Password copied"
},
"uri": {
"message": "URI",
"description": "URI"
},
"addedSite": {
"message": "Added site",
"description": "Added site"
},
"editedSite": {
"message": "Edited site",
"description": "Edited site"
},
"deleteSiteConfirmation": {
"message": "Are you sure you want to delete this site?",
"description": "Are you sure you want to delete this site?"
},
"deletedSite": {
"message": "Deleted site",
"description": "Deleted site"
},
"overwritePassword": {
"message": "Overwrite Password",
"description": "Overwrite Password"
},
"overwritePasswordConfirmation": {
"message": "Are you sure you want to overwrite the current password?",
"description": "Are you sure you want to overwrite the current password?"
}
}

View File

@ -12,11 +12,11 @@
$scope.submitPromise = null;
$scope.submit = function (model) {
if (!model.email) {
toastr.error('Email address is required.', 'Errors have occurred');
toastr.error(i18nService.emailRequired, i18nService.errorsOccurred);
return;
}
if (model.email.indexOf('@') === -1) {
toastr.error('Invalid email address.', 'Errors have occurred');
toastr.error(i18nService.invalidEmail, i18nService.errorsOccurred);
return;
}
@ -24,7 +24,7 @@
$scope.submitPromise = hintPromise(request);
$scope.submitPromise.then(function () {
$analytics.eventTrack('Requested Hint');
toastr.success('We\'ve sent you an email with your master password hint.');
toastr.success(i18nService.masterPassSent);
$state.go('login');
});
};

View File

@ -20,15 +20,15 @@
$scope.loginPromise = null;
$scope.login = function (model) {
if (!model.email) {
toastr.error('Email address is required.', 'Errors have occurred');
toastr.error(i18nService.emailRequired, i18nService.errorsOccurred);
return;
}
if (model.email.indexOf('@') === -1) {
toastr.error('Invalid email address.', 'Errors have occurred');
toastr.error(i18nService.invalidEmail, i18nService.errorsOccurred);
return;
}
if (!model.masterPassword) {
toastr.error('Master password is required.', 'Errors have occurred');
toastr.error(i18nService.masterPassRequired, i18nService.errorsOccurred);
return;
}

View File

@ -11,7 +11,7 @@
$scope.loginPromise = null;
$scope.login = function (model) {
if (!model.code) {
toastr.error('Verification code is required.', 'Errors have occurred');
toastr.error(i18nService.verificationCodeRequired, i18nService.errorsOccurred);
return;
}

View File

@ -13,23 +13,23 @@
$scope.submitPromise = null;
$scope.submit = function (model) {
if (!model.email) {
toastr.error('Email address is required.', 'Errors have occurred');
toastr.error(i18nService.emailRequired, i18nService.errorsOccurred);
return;
}
if (model.email.indexOf('@') === -1) {
toastr.error('Invalid email address.', 'Errors have occurred');
toastr.error(i18nService.invalidEmail, i18nService.errorsOccurred);
return;
}
if (!model.masterPassword) {
toastr.error('Master password is required.', 'Errors have occurred');
toastr.error(i18nService.masterPassRequired, i18nService.errorsOccurred);
return;
}
if (model.masterPassword.length < 8) {
toastr.error('Master password must be at least 8 characters long.', 'Errors have occurred');
toastr.error(i18nService.masterPassLength, i18nService.errorsOccurred);
return;
}
if (model.masterPassword !== model.masterPasswordRetype) {
toastr.error('Master password confirmation does not match.', 'Errors have occurred');
toastr.error(i18nService.masterPassDoesntMatch, i18nService.errorsOccurred);
return;
}
@ -38,7 +38,7 @@
$scope.submitPromise = registerPromise(key, model.masterPassword, email, model.hint);
$scope.submitPromise.then(function () {
$analytics.eventTrack('Registered');
toastr.success('Your new account has been created! You may now log in.');
toastr.success(i18nService.newAccountCreated);
$state.go('login', { email: email, animation: 'in-slide-left' });
});
};

View File

@ -58,8 +58,8 @@ angular
$scope.clipboardSuccess = function (e, type) {
e.clearSelection();
toastr.info(type + ' copied!');
$analytics.eventTrack('Copied ' + type);
toastr.info(type + i18nService.valueCopied);
$analytics.eventTrack('Copied ' + (type === i18nService.username ? 'Username' : 'Password'));
};
$scope.addSite = function () {
@ -87,8 +87,7 @@ angular
}
else {
$analytics.eventTrack('Autofilled Error');
toastr.error('Unable to auto-fill the selected site on this page. ' +
'Copy/paste your username and/or password instead.');
toastr.error(i18nService.autofillError);
}
};

View File

@ -12,13 +12,13 @@
title="Auto-fill {{site.name}}" ng-repeat="site in theSites = (sites | orderBy: ['name', 'username'])">
<span class="btn-list" href="" ng-click="$event.stopPropagation()" title="{{i18n.copyPassword}}"
ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, 'Password')"
ngclipboard-success="clipboardSuccess(e, i18n.password)"
data-clipboard-text="{{site.password}}" ng-class="{'disabled': !site.password}">
<i class="fa fa-lg fa-key"></i>
</span>
<span class="btn-list" href="" ng-click="$event.stopPropagation()" title="{{i18n.copyUsername}}"
ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, 'Username')"
ngclipboard-success="clipboardSuccess(e, i18n.username)"
data-clipboard-text="{{site.username}}" ng-class="{'disabled': !site.username}">
<i class="fa fa-lg fa-user"></i>
</span>

View File

@ -1,7 +1,7 @@
angular
.module('bit.global')
.controller('mainController', function ($scope, $state, loginService, toastr) {
.controller('mainController', function ($scope, $state, loginService, toastr, i18nService) {
var self = this;
self.currentYear = new Date().getFullYear();
self.animation = '';
@ -25,7 +25,7 @@ angular
}
else if (msg.command === 'logout') {
loginService.logOut(function () {
toastr.warning('Your login session has expired.', 'Logged out');
toastr.warning(i18nService.loginExpired, i18nService.loggedOut);
$state.go('home');
});
}

View File

@ -8,11 +8,11 @@
$scope.logOut = function () {
SweetAlert.swal({
title: 'Log Out',
text: 'Are you sure you want to log out?',
title: i18nService.logOut,
text: i18nService.logOutConfirmation,
showCancelButton: true,
confirmButtonText: 'Yes',
cancelButtonText: 'Cancel'
confirmButtonText: i18nService.yes,
cancelButtonText: i18nService.cancel
}, function (confirmed) {
if (confirmed) {
loginService.logOut(function () {

View File

@ -1,11 +1,11 @@
angular
.module('bit.services')
.factory('validationService', function (toastr) {
.factory('validationService', function (toastr, i18nService) {
var _service = {};
_service.showError = function (data) {
var defaultErrorMessage = 'An unexpected error has occured.';
var defaultErrorMessage = i18nService.unexpectedError;
var errors = [];
if (!data || !angular.isObject(data)) {
@ -32,7 +32,7 @@
}
if (errors.length) {
toastr.error(errors[0], 'Errors have occurred');
toastr.error(errors[0], i18nService.errorsOccurred);
}
return errors;

View File

@ -11,7 +11,7 @@ angular
$scope.savePromise = null;
$scope.save = function (model) {
if (!model.name) {
toastr.error('Name is required.', 'Errors have occurred');
toastr.error(i18nService.nameRequired, i18nService.errorsOccurred);
return;
}
@ -19,7 +19,7 @@ angular
var folder = new Folder(folderModel, true);
return $q.when(folderService.saveWithServer(folder)).then(function (folder) {
$analytics.eventTrack('Added Folder');
toastr.success('Added folder');
toastr.success(i18nService.addedFolder);
$state.go('folders', { animation: 'out-slide-down' });
});
});

View File

@ -40,12 +40,11 @@
}
else {
SweetAlert.swal({
title: 'Logging out',
text: 'You\'ve recently updated to v1.2.0. You must re-log in to change your lock options. ' +
'Do you want to log out now?',
title: i18nService.loggingOut,
text: i18nService.loggingOutConfirmation,
showCancelButton: true,
confirmButtonText: 'Yes',
cancelButtonText: 'Cancel'
confirmButtonText: i18nService.yes,
cancelButtonText: i18nService.cancel
}, function (confirmed) {
if (confirmed) {
cryptoService.toggleKey(function () { });
@ -62,11 +61,11 @@
$scope.logOut = function () {
SweetAlert.swal({
title: 'Log Out',
text: 'Are you sure you want to log out?',
title: i18nService.logOut,
text: i18nService.logOutConfirmation,
showCancelButton: true,
confirmButtonText: 'Yes',
cancelButtonText: 'Cancel'
confirmButtonText: i18nService.yes,
cancelButtonText: i18nService.cancel
}, function (confirmed) {
if (confirmed) {
loginService.logOut(function () {
@ -79,12 +78,11 @@
$scope.changePassword = function () {
SweetAlert.swal({
title: 'Change Master Password',
text: 'You can change your master password on the bitwarden.com web vault. Do you want to visit the ' +
'website now?',
title: i18nService.changeMasterPassword,
text: i18nService.changeMasterPasswordConfirmation,
showCancelButton: true,
confirmButtonText: 'Yes',
cancelButtonText: 'Cancel'
confirmButtonText: i18nService.yes,
cancelButtonText: i18nService.cancel
}, function (confirmed) {
$analytics.eventTrack('Clicked Change Password');
alertCallback(confirmed);
@ -93,12 +91,11 @@
$scope.changeEmail = function () {
SweetAlert.swal({
title: 'Change Email',
text: 'You can change your email address on the bitwarden.com web vault. Do you want to visit the ' +
'website now?',
title: i18nService.changeEmail,
text: i18nService.changeEmailConfirmation,
showCancelButton: true,
confirmButtonText: 'Yes',
cancelButtonText: 'Cancel'
confirmButtonText: i18nService.yes,
cancelButtonText: i18nService.cancel
}, function (confirmed) {
$analytics.eventTrack('Clicked Change Email');
alertCallback(confirmed);
@ -107,13 +104,11 @@
$scope.twoStep = function () {
SweetAlert.swal({
title: 'Two-step Login',
text: 'Two-step login makes your account more secure by requiring you to enter a security code from an ' +
'authenticator app whenever you log in. Two-step login can be enabled on the bitwarden.com web vault. ' +
'Do you want to visit the website now?',
title: i18nService.twoStepLogin,
text: i18nService.twoStepLoginConfirmation,
showCancelButton: true,
confirmButtonText: 'Yes',
cancelButtonText: 'Cancel'
confirmButtonText: i18nService.yes,
cancelButtonText: i18nService.cancel
}, function (confirmed) {
$analytics.eventTrack('Clicked Two-step Login');
alertCallback(confirmed);

View File

@ -18,7 +18,7 @@
$scope.savePromise = null;
$scope.save = function (model) {
if (!model.name) {
toastr.error('Name is required.', 'Errors have occurred');
toastr.error(i18nService.nameRequired, i18nService.errorsOccurred);
return;
}
@ -26,7 +26,7 @@
var folder = new Folder(folderModel, true);
return $q.when(folderService.saveWithServer(folder)).then(function (folder) {
$analytics.eventTrack('Edited Folder');
toastr.success('Edited folder');
toastr.success(i18nService.editedFolder);
$state.go('folders', { animation: 'out-slide-down' });
});
});
@ -34,16 +34,16 @@
$scope.delete = function () {
SweetAlert.swal({
title: 'Delete Folder',
text: 'Are you sure you want to delete this folder?',
title: i18nService.deleteFolder,
text: i18nService.deleteFolderConfirmation,
showCancelButton: true,
confirmButtonText: 'Yes',
cancelButtonText: 'No'
confirmButtonText: i18nService.yes,
cancelButtonText: i18nService.no
}, function (confirmed) {
if (confirmed) {
$q.when(folderService.deleteWithServer(folderId)).then(function () {
$analytics.eventTrack('Deleted Folder');
toastr.success('Deleted folder');
toastr.success(i18nService.deletedFolder);
$state.go('folders', {
animation: 'out-slide-down'
});

View File

@ -13,6 +13,11 @@
chrome.tabs.create({ url: 'https://bitwarden.com/contact/' });
};
$scope.tutorial = function () {
$analytics.eventTrack('Selected Help Tutorial');
chrome.tabs.create({ url: 'https://bitwarden.com/browser-start/' });
};
$scope.bug = function () {
$analytics.eventTrack('Selected Help Bug Report');
chrome.tabs.create({ url: 'https://github.com/bitwarden/browser' });

View File

@ -12,7 +12,7 @@
syncService.fullSync(function () {
$analytics.eventTrack('Synced Full');
$scope.loading = false;
toastr.success('Syncing complete');
toastr.success(i18nService.syncingComplete);
setLastSync();
});
};
@ -23,7 +23,7 @@
$scope.lastSync = lastSync.toLocaleDateString() + ' ' + lastSync.toLocaleTimeString();
}
else {
$scope.lastSync = 'Never';
$scope.lastSync = i18nService.never;
}
});
}

View File

@ -28,6 +28,17 @@
{{i18n.visitOurWebsiteDirectly}}
</div>
</div>
<div class="list-section">
<div class="list-section-items">
<a class="list-section-item" href="" ng-click="tutorial()">
{{i18n.gettingStartedTutorial}}
<i class="fa fa-chevron-right fa-lg"></i>
</a>
</div>
<div class="list-section-footer">
{{i18n.gettingStartedTutorialVideo}}
</div>
</div>
<div class="list-section">
<div class="list-section-items">
<a class="list-section-item" href="" ng-click="bug()">

View File

@ -17,11 +17,11 @@
$scope.launchImport = function () {
SweetAlert.swal({
title: 'Import Logins',
text: 'You can bulk import logins from the bitwarden.com web vault. Do you want to visit the website now?',
title: i18nService.importLogins,
text: i18nService.importLoginsConfirmation,
showCancelButton: true,
confirmButtonText: 'Yes',
cancelButtonText: 'Cancel'
confirmButtonText: i18nService.yes,
cancelButtonText: i18nService.cancel
}, function (confirmed) {
if (confirmed) {
chrome.tabs.create({ url: 'https://vault.bitwarden.com' });

View File

@ -69,7 +69,7 @@
$scope.clipboardSuccess = function (e) {
$analytics.eventTrack('Copied Generated Password');
e.clearSelection();
toastr.info('Password copied!');
toastr.info(i18nService.passwordCopied);
};
$scope.close = function () {

View File

@ -33,7 +33,7 @@
$scope.savePromise = null;
$scope.save = function (model) {
if (!model.name) {
toastr.error('Name is required.', 'Errors have occurred');
toastr.error(i18nService.nameRequired, i18nService.errorsOccurred);
return;
}
@ -41,7 +41,7 @@
var site = new Site(siteModel, true);
return $q.when(siteService.saveWithServer(site)).then(function (site) {
$analytics.eventTrack('Added Site');
toastr.success('Added site');
toastr.success(i18nService.addedSite);
$scope.close();
});
});

View File

@ -115,8 +115,8 @@
$scope.clipboardSuccess = function (e, type) {
e.clearSelection();
$analytics.eventTrack('Copied ' + type);
toastr.info(type + ' copied!');
$analytics.eventTrack('Copied ' + (type === i18nService.username ? 'Username' : 'Password'));
toastr.info(type + i18nService.valueCopied);
};
$scope.$on('syncCompleted', function (event, successfully) {

View File

@ -34,7 +34,7 @@ angular
$scope.savePromise = null;
$scope.save = function (model) {
if (!model.name) {
toastr.error('Name is required.', 'Errors have occurred');
toastr.error(i18nService.nameRequired, i18nService.errorsOccurred);
return;
}
@ -42,7 +42,7 @@ angular
var site = new Site(siteModel, true);
return $q.when(siteService.saveWithServer(site)).then(function (site) {
$analytics.eventTrack('Edited Site');
toastr.success('Edited site');
toastr.success(i18nService.editedSite);
$scope.close();
});
});
@ -50,16 +50,16 @@ angular
$scope.delete = function () {
SweetAlert.swal({
title: 'Delete Site',
text: 'Are you sure you want to delete this site?',
title: i18nService.deleteSite,
text: i18nService.deleteSiteConfirmation,
showCancelButton: true,
confirmButtonText: 'Yes',
cancelButtonText: 'No'
confirmButtonText: i18nService.yes,
cancelButtonText: i18nService.no
}, function (confirmed) {
if (confirmed) {
$q.when(siteService.deleteWithServer(siteId)).then(function () {
$analytics.eventTrack('Deleted Site');
toastr.success('Deleted site');
toastr.success(i18nService.deletedSite);
$state.go('tabs.vault', {
animation: 'out-slide-down'
});
@ -90,11 +90,11 @@ angular
$scope.generatePassword = function () {
if ($scope.site.password) {
SweetAlert.swal({
title: 'Overwrite Password',
text: 'Are you sure you want to overwrite the current password?',
title: i18nService.overwritePassword,
text: i18nService.overwritePasswordConfirmation,
showCancelButton: true,
confirmButtonText: 'Yes',
cancelButtonText: 'No'
confirmButtonText: i18nService.yes,
cancelButtonText: i18nService.no
}, function (confirmed) {
if (confirmed) {
goPasswordGenerator();

View File

@ -81,8 +81,8 @@ angular
$scope.clipboardSuccess = function (e, type) {
e.clearSelection();
$analytics.eventTrack('Copied ' + type);
toastr.info(type + ' copied!');
$analytics.eventTrack('Copied ' + (type === i18nService.username ? 'Username' : 'Password'));
toastr.info(type + i18nService.valueCopied);
};
$scope.showPassword = false;

View File

@ -20,12 +20,12 @@
ng-repeat="site in folderSites = (vaultSites | filter: { folderId: folder.id }
| filter: searchSites() | orderBy: ['name', 'username'])">
<span class="btn-list" ng-click="$event.stopPropagation()" title="{{i18n.copyPassword}}" ngclipboard
ngclipboard-error="clipboardError(e)" ngclipboard-success="clipboardSuccess(e, 'Password')"
ngclipboard-error="clipboardError(e)" ngclipboard-success="clipboardSuccess(e, i18n.password)"
data-clipboard-text="{{site.password}}" ng-class="{'disabled': !site.password}">
<i class="fa fa-lg fa-key"></i>
</span>
<span class="btn-list" ng-click="$event.stopPropagation()" title="{{i18n.copyUsername}}" ngclipboard
ngclipboard-error="clipboardError(e)" ngclipboard-success="clipboardSuccess(e, 'Username')"
ngclipboard-error="clipboardError(e)" ngclipboard-success="clipboardSuccess(e, i18n.username)"
data-clipboard-text="{{site.username}}" ng-class="{'disabled': !site.username}">
<i class="fa fa-lg fa-user"></i>
</span>

View File

@ -21,7 +21,7 @@
<input id="name" type="text" name="Name" ng-model="site.name">
</div>
<div class="list-section-item">
<label for="uri" class="item-label">URI</label>
<label for="uri" class="item-label">{{i18n.uri}}</label>
<input id="uri" type="text" name="Uri" ng-model="site.uri">
</div>
<div class="list-section-item">

View File

@ -21,7 +21,7 @@
<input id="name" type="text" name="Name" ng-model="site.name">
</div>
<div class="list-section-item">
<label for="uri" class="item-label">URI</label>
<label for="uri" class="item-label">{{i18n.uri}}</label>
<input id="uri" type="text" name="Uri" ng-model="site.uri">
</div>
<div class="list-section-item">

View File

@ -28,7 +28,7 @@
</div>
<div class="list-section-item" ng-if="site.username">
<a class="btn-list" href="" title="{{i18n.copyUsername}}" ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, 'Username')" data-clipboard-target="#username">
ngclipboard-success="clipboardSuccess(e, i18n.username)" data-clipboard-target="#username">
<i class="fa fa-lg fa-clipboard"></i>
</a>
<span class="item-label">{{i18n.username}}</span>
@ -36,7 +36,7 @@
</div>
<div class="list-section-item" ng-if="site.password">
<a class="btn-list" href="" title="{{i18n.copyPassword}}" ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, 'Password')" data-clipboard-target="#password">
ngclipboard-success="clipboardSuccess(e, i18n.password)" data-clipboard-target="#password">
<i class="fa fa-lg fa-clipboard"></i>
</a>
<a class="btn-list" href="" title="{{i18n.togglePassword}}" ng-click="togglePassword()">