Merge pull request #2 from bitpay/master

Sync with master
This commit is contained in:
Rich Morgan 2015-09-03 11:56:35 -04:00
commit 51f0071b7a
116 changed files with 14896 additions and 4881 deletions

6
.gitignore vendored
View File

@ -1,5 +1,6 @@
# translation
po/*.mo
i18n/po/*.mo
i18n/crowdin_api_key.txt
src/js/translations.js
# version
@ -26,9 +27,6 @@ browser-extensions/chrome/copay-chrome-extension.zip
logs
*.log
# readme
README.html
# Runtime data
pids
*.pid

View File

@ -1,45 +0,0 @@
CHANGES
=======
v0.2.1
------
New features
------------
* Smart backup restore procedure: now it is possible to restore all wallet's fund with an old backup (thanks Ian for the feedback).
* Transaction proposals can now have a short note attached for reference (thanks Gentry for the feedback).
* New wallet settings: Bitcoin Unit, defaults to *bits* (thanks Eric for the suggestion)
* Backup is now auto generated on wallet completion (thanks Eric for the suggestion)
* A wallet now can be removed from a particular system from the UX.
* New address book shared between copayers.
Security
--------
* Asymmetric encryption and signing using ECIES. Details at https://gist.github.com/ryanxcharles/c29fc94d31de7c8c89dc
* Default SSL connection to Insight and PeerJs servers
Code quality
------------
* Test coverage from 60.9% to 74% (1) (thanks Ryan for insisting on this)
* Mayor refactoring of Angular services (backupService, controllerUtils, wallet's Indexes handling, txProposal merge related functions,
* Add +30 karma tests for Angular controllers and services
* Unified js-beautifier format throw all the code
Other
-----
* Backup to email have been removed
* Performance improvements when signing transactions
* Review of Copay 1-of-1 UX
* Minor UX and wording fixes (address list on receiving funds, notifications fixes, error handling on bad passwords, network timeouts, feedback at importing process, etc).
Next steps
----------
* Make Copay available in other platforms (update Gordon's Atom shell packages, Android bundle, Firefox / Chrome extensions).
* Implement Copay 2.0 design: http://invis.io/FWZGJWUS (please take a look at leave comments)
Please check https://github.com/bitpay/copay/wiki/Copay-Known-issues before using Copay.
(1) not including Karma tests, not included on Coveralls yet.

View File

@ -1,25 +0,0 @@
# QA - Bug Reporting
To provide the most helpful bug reports to our developers, ensure that each issue/report that you create contains the following information:
- Brief description of the bug
- Steps to reproduce the bug
- Platform in which you are testing
- Screenshots if possible
- Expected behaviour
**For example:**
```
Description: The application fails at login.
1) Launch the app `npm run start`
2) Click on "Join a Wallet"
3) Type an nonexistent username
4) The app stops working and throws an "Unhandled exception" error.
Expected: The app should login and show the home screen without any error.
Platform: Android 4.3, Android 4.4, iOS
```

View File

@ -3,27 +3,6 @@ module.exports = function(grunt) {
// Project Configuration
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
release: {
options: {
bump: true,
file: 'package.json',
add: true,
commit: true,
tag: true,
push: true,
pushTags: true,
npm: false,
npmtag: true,
tagName: 'v<%= version %>',
commitMessage: 'New release v<%= version %>',
tagMessage: 'Version <%= version %>',
github: {
repo: 'bitpay/copay',
usernameVar: 'GITHUB_USERNAME', //ENVIRONMENT VARIABLE that contains Github username
passwordVar: 'GITHUB_PASSWORD' //ENVIRONMENT VARIABLE that contains Github password
}
}
},
exec: {
version: {
command: 'node ./util/version.js'
@ -45,10 +24,6 @@ module.exports = function(grunt) {
grunt.log.writeln('Waiting for more changes...');
},
},
readme: {
files: ['README.md'],
tasks: ['markdown']
},
css: {
files: ['src/css/*.css'],
tasks: ['concat:css']
@ -67,16 +42,6 @@ module.exports = function(grunt) {
tasks: ['concat:js']
}
},
markdown: {
all: {
files: [{
expand: true,
src: 'README.md',
dest: './doc',
ext: '.html'
}]
}
},
concat: {
options: {
sourceMap: false,
@ -144,7 +109,7 @@ module.exports = function(grunt) {
nggettext_extract: {
pot: {
files: {
'po/template.pot': [
'i18n/po/template.pot': [
'public/index.html',
'public/views/*.html',
'public/views/**/*.html',
@ -161,7 +126,7 @@ module.exports = function(grunt) {
module: 'copayApp'
},
files: {
'src/js/translations.js': ['po/*.po']
'src/js/translations.js': ['i18n/po/*.po']
}
},
},
@ -174,8 +139,8 @@ module.exports = function(grunt) {
},
linux: {
files: [
{expand: true, cwd: 'webkitbuilds/',src: ['.desktop', 'favicon.ico'],dest: 'webkitbuilds/copay/linux32/', flatten: true, filter: 'isFile' },
{expand: true, cwd: 'webkitbuilds/',src: ['.desktop', 'favicon.ico'],dest: 'webkitbuilds/copay/linux64/', flatten: true, filter: 'isFile' },
{expand: true, cwd: 'webkitbuilds/',src: ['.desktop', '../public/img/icons/favicon.ico', '../public/img/icons/icon-256.png'],dest: 'webkitbuilds/copay/linux32/', flatten: true, filter: 'isFile' },
{expand: true, cwd: 'webkitbuilds/',src: ['.desktop', '../public/img/icons/favicon.ico', '../public/img/icons/icon-256.png'],dest: 'webkitbuilds/copay/linux64/', flatten: true, filter: 'isFile' },
],
}
},
@ -234,20 +199,14 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-angular-gettext');
grunt.loadNpmTasks('grunt-markdown');
grunt.loadNpmTasks('grunt-release');
grunt.loadNpmTasks('grunt-exec');
grunt.loadNpmTasks('grunt-karma');
grunt.loadNpmTasks('grunt-karma-coveralls');
grunt.loadNpmTasks('grunt-node-webkit-builder');
grunt.loadNpmTasks('grunt-contrib-compress');
grunt.registerTask('default', [
'nggettext_compile', 'exec:version', 'concat', 'copy:icons'
]);
grunt.registerTask('prod', [
'default', 'uglify'
]);
grunt.registerTask('default', ['nggettext_compile', 'exec:version', 'concat', 'copy:icons']);
grunt.registerTask('prod', ['default', 'uglify']);
grunt.registerTask('translate', ['nggettext_extract']);
grunt.registerTask('test', ['karma:unit']);
grunt.registerTask('test-coveralls', ['karma:prod', 'coveralls']);

View File

@ -1,6 +1,7 @@
<img src="https://raw.githubusercontent.com/bitpay/copay/master/public/img/logo.png" alt="Copay" width="300">
[![Build Status](https://secure.travis-ci.org/bitpay/copay.svg)](http://travis-ci.org/bitpay/copay)
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/copay/localized.png)](https://crowdin.com/project/copay)
Copay is an easy-to-use, open-source, multiplatform, multisignature, secure bitcoin wallet platform for both individuals and companies. Copay uses [Bitcore Wallet Service](https://github.com/bitpay/bitcore-wallet-service) (BWS) for peer synchronization and bitcore network interfacing.
@ -95,12 +96,32 @@ Copay also implements [BIP32](https://github.com/bitcoin/bips/blob/master/bip-00
For more information regarding how addresses are generated using this procedure, see: [Structure for Deterministic P2SH Multisignature Wallets](https://github.com/bitcoin/bips/blob/master/bip-0045.mediawiki).
## Backup format
Copay encrypts the backup with the Stanford JS Cryto Library (https://crypto.stanford.edu/sjcl/). To extract the private key of your wallet you can use https://bitwiseshiftleft.github.io/sjcl/demo/, copy the backup to 'ciphertext' and enter your password. The resulting JSON will have a key named: `xPrivKey`, that is the extended private key of your wallet. That information is enought to sign any transaction of your wallet, so be careful handling it.
The backup also contains the key `publicKeyRing` that hold the extended public keys of the Copayers. Using a tool like [Bitcore PlayGround](http://bitcore.io/playground/#/multisig), and following [BIP45](https://github.com/bitcoin/bips/blob/master/bip-0045.mediawiki) it is possible to generate all wallet address. Note that addresses generated at BWS use the 'shared cosigner index' (2147483647) so Copay address index look like:
`m/45'/2147483647/0/x` for main addresses and
`m/45'/2147483647/1/y` for change addresses, where `x` and `y` are integers starting from `0`. The maximun values of `x` and `y` depend on the wallet usage, and in a restore procedure, the generated addresses are scanned on the blockchain looking for transactions (this is the 'scan' procedure that you can see on Settings at Copay App). To generate the wallet addresses the required number of copayers also need to be specified (backup key `m`).
## Bitcore Wallet Service
Copay depends on [Bitcore Wallet Service](https://github.com/bitpay/bitcore-wallet-service) (BWS) for blockchain information, networking and copayer synchronization. A BWS instance can be setup and operational within minutes or you can use a public instance like `https://bws.bitpay.com`. Switching between BWS instances is very simple and can be done with a click from within Copay. BWS also allows Copay to interoperate with others wallet like [Bitcore Wallet CLI] (https://github.com/bitpay/bitcore-wallet).
## Translations
Copay uses standard gettext PO files for translations and is currently translated to Spanish, Japanese, French, German and Portuguese thanks to community contributions. See https://github.com/bitpay/copay/pull/2880 as an example pull request for adding translations.
Copay uses standard gettext PO files for translations and [Crowdin](https://crowdin.com/project/copay) as front-end for translators.
To join our team of translators, please create an account at [Crowdin](https://crowdin.com) and translate into your native language to help spread Multisig.
To download and build using the latest translations from crowdin, please use the following commands.
```sh
cd i18n
node crowdin_download.js
```
This will download all partially/completely translated languages and clean out any un-translated ones.
**Translation Credits:**
- Japanese: @dabura667
@ -108,5 +129,25 @@ Copay uses standard gettext PO files for translations and is currently translate
- Portuguese: @pmichelazzo
- Spanish: @cmgustavo
- German: @saschad
- Russian: @vadim0
*Gracias totales!*
## Release schedules
Copay uses following convention for versioning:
```
MAJOR.MINOR.BATCH, eg: 1.1.3
```
Any release that adds features should modify the MINOR or MAJOR number.
### Bug Fixing Releases
We release it ASAP in all platforms. As soon as the bug is fixed, we release the new version to all platforms. A week later we can send a new release with translation update (like 1.1.4 and then 1.1.5). There is no coordination so all platforms are updated at the same time.
### Minor and Major releases
- t+0: tag the release 1.2 and "text lock" (meaning, only non-text related bug fixes. Though this rule is sometimes broken, it's good to make a rule.)
- t+7: testing for 1.2 is finished, translation is also finished, and 1.2.1 is tagged with all translations and bug fixes made in the last week.
- t+7: iOS is submitted for 1.2.1. All other platforms submitted with auto-release off.
- t + (~17): All platforms 1.2.1 is released when iOS approves.

View File

@ -15,9 +15,9 @@
"foundation": "zurb/bower-foundation#~5.5.1",
"foundation-icon-fonts": "*",
"ng-lodash": "~0.2.0",
"angular-moment": "~0.10.1",
"moment": "~2.10.3",
"angular-bitcore-wallet-client": "^0.0.26",
"angular-moment": "0.10.1",
"moment": "2.10.3",
"angular-bitcore-wallet-client": "^0.1.2",
"angular-ui-router": "~0.2.13",
"qrcode-decoder-js": "*",
"fastclick": "*",

View File

@ -14,6 +14,6 @@
}
},
"icons": {
"128": "img/icons/icon.png"
"128": "img/icons/icon-chrome-128.png"
}
}

View File

@ -1,8 +1,8 @@
<?xml version='1.0' encoding='utf-8'?>
<widget id="com.bitpay.copay"
version="1.1.1"
android-versionCode="38"
ios-CFBundleVersion="1.1.1">
version="1.1.3"
android-versionCode="40"
ios-CFBundleVersion="1.1.3">
<name>Copay</name>
<description>
A secure bitcoin wallet for friends and companies.

61
cordova/docs/appstore_el Normal file
View File

@ -0,0 +1,61 @@
--------------------------------
Description
--------------------------------
Εξασφαλίστε τα Bitcoin σας με τους δικούς σας όρους με ένα ανοιχτού κώδικα, πορτοφόλι πολλών υπογραφών από την BitPay.
Οι χρήστες copay μπορούν να κρατούν και να διαχειρίζονται κεφάλαια ατομικά ή να τα μοιράζονται με ασφάλεια με άλλους χρήστες με το πορτοφόλι πολλών υπογραφών, το οποίο εμποδίζει τις μη εξουσιοδοτημένες πληρωμές και απαιτεί πολλαπλές εγκρίσεις. Εδώ είναι μερικοί τρόποι με τους οποίους το copay μπορεί να χρησιμοποιηθεί σε συνδιασμό με άλλους ανθρώπους:
Για να αποθηκεύσετε για τις διακοπές σας ή να κάνετε κοινές αγορές με τους φίλους σας
Για να παρακολουθήσετε τις οικογενειακές δαπάνες και τα επιδόμάτα
Για τη διαχείριση επιχειρήσεων, κλαμπ, ή κεφάλαια οργανισμών και έξοδα οργάνωσης
Χτίσαμε τα ακόλουθα χαρακτηριστικά σε αυτή την έκδοση του copay για ένα πορτοφόλι Bitcoin που δεν θέτει σε κίνδυνο την ασφάλεια ή την προσβασιμότητα:
Δημιουργία πολλαπλών πορτοφολιών και διαχείριση εντός εφαρμογής
Διαισθητική ασφαλείας πολλών υπογραφών για προσωπικά ή κοινόχρηστα πορτοφόλια
Εύκολη ροή προτάσεων δαπάνών για κοινόχρηστα πορτοφόλια και πληρωμές ομάδων
Ιεραρχική ντετερμινιστική δημιουργία διευθύνσεων (HD) και αντιγράφων ασφαλείας πορτοφολιού
Ασφάλεια με βάση τη συσκευή: όλα τα ιδιωτικά κλειδιά αποθηκεύονται τοπικά, όχι στο σύννεφο
Υποστήριξη για πορτοφόλια του δοκιμαστικού δικτύου Bitcoin
Σύγχρονισμένη πρόσβαση σε όλες τις μεγάλες πλατφόρμες, φορητές και επιτραπέζιες
Πρωτόκολλο πληρωμής (BIP70-BIP73) το οποίο υποστηρίζει: εύκολα αναγνωρίσιμες αιτήσεις πληρωμής και διασφάλισμένες και επαληθεύσιμες πληρωμές με Bitcoin
Υποστήριξη για επιλογές τιμολόγησης 150+ νομισμάτων και ονομαστική αξία σε BTC ή bits
Ειδοποιήσεις μέσω email για πληρωμές και μεταφορές
Προσαρμόσιμο όνομα πορτοφολιών και χρώματα φόντου
4 υποστηριζόμενες γλώσσες (Αγγλικά, Ιαπωνικά, Γαλλικά, Ισπανικά)
Το Copay είναι ελεύθερο και ανοικτού κώδικα λογισμικό το οποίο τρέχει σε μη ιδιόκτητους διακομιστές, έτσι δεν υπάρχει καμία ανάγκη να στηριχθεί σε οποιαδήποτε εταιρεία για να έχει συνεχή υποστήριξη. Ο καθένας μπορεί να αναθεωρήσει ή να συμβάλει στον πηγαίο κώδικα του copay στο GitHub (https://github.com/bitpay/copay).
--------------------------------
Release Notes: "What's new"
--------------------------------
v1.1.2
--------------------------------
* Τώρα είναι δυνατό να κάνετε αντίγραφα ασφαλείας, χωρίς δυνατότητες ψηφιακής υπογραφής (για περισσότερες πληροφορίες δείτε εδώ https://github.com/bitpay/copay/pull/2998)
* Βελτίωση των κανόνων ανανέωσης και της διαλογής στο ιστορικό συναλλαγών
* Καλύτερη διαχείριση των `λανθασμένων` συναλλαγών στο ιστορικό
* Καλύτερη διαχείριση των πορτοφολιών με 1000+ συναλλαγές στο ιστορικό τους
* Εξάγει τα αρχεία .csv με αναγνωριστικό συναλλαγής
* Καλύτερη πολιτική επιλογής αξόδευτων συναλλαγών
* Μικρές διορθώσεις σφαλμάτων
--------------------------------
v1.1.0
--------------------------------
QR κώδικες με συγκεκριμένο ποσό για την είσπραξη πληρωμών
Μεταφορά χρημάτων μεταξύ πορτοφολιών
Ειδοποιήσεις ηλεκτρονικού ταχυδρομείου σε μορφή HTML
Προσαρμοσμένες ρυθμίσεις εξόδων συναλλαγών
Αποστολή ανώτατου ορίου των χρημάτων
Νέοι κανόνες διαγραφής πρότάσεων δαπανών
Διορθώσεις σφαλμάτων στη λειτουργία εκτός σύνδεσης
--------------------------------
v1.0.2
--------------------------------
Το Copay είναι εκτός της δοκιμαστικής έκδοσης Βήτα! Έχουμε ολοκληρώσει οκτώ μήνες δοκιμών με το copay, και είμαστε έτοιμοι για την παραγωγή.
--------------------------------
v1.0.1
--------------------------------
Καλύτερη διαχείριση των σφαλμάτων διακοπής του δικτύου
Καλύτερη λογική ανανέωσης μετά την αποδοχή/απόρριψη πληρωμών
Ενημερώσεις στις μεταφράσεις των Ισπανικών των Γαλλικών και των Ιαπωνικών
Διορθώσαμε την λειτουργία μετακίνησης μεσα σε ορισμένα πλαίσια κειμένου
--------------------------------

View File

@ -57,11 +57,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.1.1</string>
<string>1.1.3</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.1.1</string>
<string>1.1.3</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSMainNibFile</key>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest" xmlns:m2="http://schemas.microsoft.com/appx/2013/manifest" xmlns:m3="http://schemas.microsoft.com/appx/2014/manifest" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest">
<Identity Name="18C7659D.CopayWallet" Publisher="CN=F89609D1-EB3E-45FD-A58A-C2E3895FCE7B" Version="1.1.1.0" />
<Identity Name="18C7659D.CopayWallet" Publisher="CN=F89609D1-EB3E-45FD-A58A-C2E3895FCE7B" Version="1.1.3.0" />
<mp:PhoneIdentity PhoneProductId="5381aa50-9069-11e4-84cc-293caf9cbdc8" PhonePublisherId="F89609D1-EB3E-45FD-A58A-C2E3895FCE7B" />
<Properties>
<DisplayName>Copay Wallet</DisplayName>

248
i18n/crowdin_download.js Normal file
View File

@ -0,0 +1,248 @@
#!/usr/bin/env node
'use strict';
if (process.argv[2]) {
var no_key = (process.argv[2].toLowerCase() == '--nokey')
if (no_key == false) {
console.log('Incorrect arg. Please use --nokey if you would like to download without api key.');
process.exit(1);
};
} else {
var no_key = false;
console.log('\n' +
'Please note: If you do not have the crowdin API key and would like to download the ' +
'translations without building anyways, please make sure your English files are the same ' +
'version as crowdin, and then run this script with --nokey\n\n' +
'eg. "node crowdin_download.js --nokey"\n\n');
};
var fs = require('fs');
var path = require('path');
var https = require('https');
var AdmZip = require('adm-zip');
var crowdin_identifier = 'copay'
var local_file_name2 = path.join(__dirname, 'docs/appstore_en.txt')
var local_file_name3 = path.join(__dirname, 'docs/updateinfo_en.txt')
try {
fs.statSync(local_file_name2);
fs.statSync(local_file_name3);
}
catch (e) {
console.log('\n### ABORTING ### One of the following files does not exist:\n' + local_file_name2 + '\n' + local_file_name3);
process.exit(1);
}
if (no_key == false) { // Reminder: Any changes to the script below must also be made to the else clause and vice versa.
try {
// obtain the crowdin api key
var crowdin_api_key = fs.readFileSync(path.join(__dirname, 'crowdin_api_key.txt'), 'utf8')
} catch (e) {
console.log('### ERROR ### You do not have the crowdin api key in ./crowdin_api_key.txt so the translation build has failed.\nFor download only use --nokey.');
process.exit(1);
};
// This call will tell the server to generate a new zip file for you based on most recent translations.
https.get('https://api.crowdin.com/api/project/' + crowdin_identifier + '/export?key=' + crowdin_api_key, function(res) {
console.log('Export Got response: ' + res.statusCode);
res.on('data', function(chunk) {
var resxml = chunk.toString('utf8');
console.log(resxml);
if (resxml.indexOf('status="skipped"') >= 0) {
console.log('Translation build was skipped due to either:\n' +
'1. No changes since last translation build, or\n' +
'2. API limit of once per 30 minutes has not been waited.\n\n' +
'Since we can not guarantee that translations have been built properly, this script will end here.\n' +
'Log in to Copay\'s Crowdin Settings and click the "Build Project" button to assure it is built recently, and then run this ' +
'script again with the --nokey arg to download translations without checking if built.');
process.exit(1);
};
// Download most recent translations for all languages.
https.get('https://crowdin.com/download/project/' + crowdin_identifier + '.zip', function(res) {
var data = [], dataLen = 0;
res.on('data', function(chunk) {
data.push(chunk);
dataLen += chunk.length;
}).on('end', function() {
var buf = new Buffer(dataLen);
for (var i=0, len = data.length, pos = 0; i < len; i++) {
data[i].copy(buf, pos);
pos += data[i].length;
};
var zip = new AdmZip(buf);
zip.extractAllTo('./', true);
console.log('Done extracting ZIP file.');
var files = fs.readdirSync('./docs');
for (var i in files) {
debugger;
if (files[i].slice(0,9) == 'appstore_' && files[i].slice(-4) == '.txt' && files[i] != 'appstore_en.txt') {
var english_file = fs.readFileSync(local_file_name2, 'utf8');
var compare_file = fs.readFileSync(path.join(__dirname, 'docs/' + files[i]), 'utf8')
english_file = english_file.replace(/\r\n/g, '\n');
compare_file = compare_file.replace(/\r\n/g, '\n');
if (compare_file == english_file) {
fs.unlinkSync(path.join(__dirname, 'docs/' + files[i]));
};
};
if (files[i].slice(0,11) == 'updateinfo_' && files[i].slice(-4) == '.txt' && files[i] != 'updateinfo_en.txt') {
var english_file = fs.readFileSync(local_file_name3, 'utf8');
var compare_file = fs.readFileSync(path.join(__dirname, 'docs/' + files[i]), 'utf8')
english_file = english_file.replace(/\r\n/g, '\n');
compare_file = compare_file.replace(/\r\n/g, '\n');
if (compare_file == english_file) {
fs.unlinkSync(path.join(__dirname, 'docs/' + files[i]));
};
};
};
console.log('Cleaned out completely untranslated appstore docs.');
var files = fs.readdirSync('./po');
for (var i in files) {
if (files[i] != 'template.pot') {
var po_file = fs.readFileSync(path.join(__dirname, 'po/' + files[i]), 'utf8');
var po_array = po_file.split('\n');
for (var j in po_array) {
if (po_array[j].slice(0,5) == 'msgid') {
var source_text = po_array[j].slice(5);
} else if (po_array[j].slice(0,6) == 'msgstr') {
var translate_text = po_array[j].slice(6);
// if a line is not == English, it means there is translation. Keep this file.
if (source_text != translate_text) {
// erase email addresses of last translator for privacy
po_file = po_file.replace(/ <.+@.+\..+>/, '')
fs.writeFileSync(path.join(__dirname, 'po/' + files[i]), po_file);
// split the file into 3 parts, before locale, locale, and after locale.
var lang_pos = po_file.search('"Language: ') + 11;
var po_start = po_file.slice(0,lang_pos);
var po_locale = po_file.slice(lang_pos,lang_pos + 5);
var po_end = po_file.slice(lang_pos + 5);
// check for underscore, if it's there, only take the first 2 letters and reconstruct the po file.
if (po_locale.search('_') > 0) {
fs.writeFileSync(path.join(__dirname, 'po/' + files[i]), po_start + po_locale.slice(0,2) + po_end);
po_start = '';
po_locale = '';
po_end = '';
};
break;
};
};
if (j == po_array.length - 1) { // All strings are exactly identical to English. Delete po file.
fs.unlinkSync(path.join(__dirname, 'po/' + files[i]));
};
};
};
};
console.log('Cleaned out completely untranslated po files.');
});
});
});
}).on('error', function(e) {
console.log('Export Got error: ' + e.message);
});
} else { // Reminder: Any changes to the script below must also be made to the above and vice versa.
// Download most recent translations for all languages.
https.get('https://crowdin.com/download/project/' + crowdin_identifier + '.zip', function(res) {
var data = [], dataLen = 0;
res.on('data', function(chunk) {
data.push(chunk);
dataLen += chunk.length;
}).on('end', function() {
var buf = new Buffer(dataLen);
for (var i=0, len = data.length, pos = 0; i < len; i++) {
data[i].copy(buf, pos);
pos += data[i].length;
};
var zip = new AdmZip(buf);
zip.extractAllTo('./', true);
console.log('Done extracting ZIP file.');
var files = fs.readdirSync('./docs');
for (var i in files) {
if (files[i].slice(0,9) == 'appstore_' && files[i].slice(-4) == '.txt' && files[i] != 'appstore_en.txt') {
var english_file = fs.readFileSync(local_file_name2, 'utf8');
var compare_file = fs.readFileSync(path.join(__dirname, 'docs/' + files[i]), 'utf8')
english_file = english_file.replace(/\r\n/g, '\n');
compare_file = compare_file.replace(/\r\n/g, '\n');
if (compare_file == english_file) {
fs.unlinkSync(path.join(__dirname, 'docs/' + files[i]));
};
};
if (files[i].slice(0,11) == 'updateinfo_' && files[i].slice(-4) == '.txt' && files[i] != 'updateinfo_en.txt') {
var english_file = fs.readFileSync(local_file_name3, 'utf8');
var compare_file = fs.readFileSync(path.join(__dirname, 'docs/' + files[i]), 'utf8')
english_file = english_file.replace(/\r\n/g, '\n');
compare_file = compare_file.replace(/\r\n/g, '\n');
if (compare_file == english_file) {
fs.unlinkSync(path.join(__dirname, 'docs/' + files[i]));
};
};
};
console.log('Cleaned out completely untranslated appstore docs.');
var files = fs.readdirSync('./po');
for (var i in files) {
if (files[i] != 'template.pot') {
var po_file = fs.readFileSync(path.join(__dirname, 'po/' + files[i]), 'utf8');
var po_array = po_file.split('\n');
for (var j in po_array) {
if (po_array[j].slice(0,5) == 'msgid') {
var source_text = po_array[j].slice(5);
} else if (po_array[j].slice(0,6) == 'msgstr') {
var translate_text = po_array[j].slice(6);
// if a line is not == English, it means there is translation. Keep this file.
if (source_text != translate_text) {
// erase email addresses of last translator for privacy
po_file = po_file.replace(/ <.+@.+\..+>/, '')
fs.writeFileSync(path.join(__dirname, 'po/' + files[i]), po_file);
// split the file into 3 parts, before locale, locale, and after locale.
var lang_pos = po_file.search('"Language: ') + 11;
var po_start = po_file.slice(0,lang_pos);
var po_locale = po_file.slice(lang_pos,lang_pos + 5);
var po_end = po_file.slice(lang_pos + 5);
// check for underscore, if it's there, only take the first 2 letters and reconstruct the po file.
if (po_locale.search('_') > 0) {
fs.writeFileSync(path.join(__dirname, 'po/' + files[i]), po_start + po_locale.slice(0,2) + po_end);
po_start = '';
po_locale = '';
po_end = '';
};
break;
};
};
if (j == po_array.length - 1) { // All strings are exactly identical to English. Delete po file.
fs.unlinkSync(path.join(__dirname, 'po/' + files[i]));
};
};
};
};
console.log('Cleaned out completely untranslated po files.');
});
});
};

66
i18n/crowdin_update.js Normal file
View File

@ -0,0 +1,66 @@
#!/usr/bin/env node
'use strict';
var fs = require('fs');
var path = require('path');
var https = require('https');
var bhttp = require('bhttp');
var crowdin_identifier = 'copay'
var local_file_name1 = path.join(__dirname, 'po/template.pot')
// Similar to Github, normalize all line breaks to CRLF so that different people
// using different OSes to update does not constantly swith format back and forth.
var local_file1_text = fs.readFileSync(local_file_name1, 'utf8');
local_file1_text = local_file1_text.replace(/\r\n/g, '\n');
local_file1_text = local_file1_text.replace(/\n/g, '\r\n');
fs.writeFileSync(local_file_name1, local_file1_text);
var local_file1 = fs.createReadStream(local_file_name1)
var local_file_name2 = path.join(__dirname, 'docs/appstore_en.txt')
var local_file2_text = fs.readFileSync(local_file_name2, 'utf8');
local_file2_text = local_file2_text.replace(/\r\n/g, '\n');
local_file2_text = local_file2_text.replace(/\n/g, '\r\n');
fs.writeFileSync(local_file_name2, local_file2_text);
var local_file2 = fs.createReadStream(local_file_name2)
var local_file_name3 = path.join(__dirname, 'docs/updateinfo_en.txt')
var local_file3_text = fs.readFileSync(local_file_name3, 'utf8');
local_file3_text = local_file3_text.replace(/\r\n/g, '\n');
local_file3_text = local_file3_text.replace(/\n/g, '\r\n');
fs.writeFileSync(local_file_name3, local_file3_text);
var local_file3 = fs.createReadStream(local_file_name3)
// obtain the crowdin api key
var crowdin_api_key = fs.readFileSync(path.join(__dirname, 'crowdin_api_key.txt'))
//console.log('api key: ' + crowdin_api_key);
if (crowdin_api_key != '') {
var payload = {
'files[template.pot]': local_file1,
'files[appstore/appstore_en.txt]': local_file2,
'files[appstore/updateinfo_en.txt]': local_file3
};
bhttp.post('https://api.crowdin.com/api/project/' + crowdin_identifier + '/update-file?key=' + crowdin_api_key, payload, {}, function(err, response) {
console.log('\nResponse from update file call:\n', response.body.toString());
// This call will tell the server to generate a new zip file for you based on most recent translations.
https.get('https://api.crowdin.com/api/project/' + crowdin_identifier + '/export?key=' + crowdin_api_key, function(res) {
console.log('Export Got response: ' + res.statusCode);
res.on('data', function(chunk) {
console.log(chunk.toString('utf8'));
});
}).on('error', function(e) {
console.log('Export Got error: ' + e.message);
});
})
};

View File

@ -1,20 +1,16 @@
--------------------------------
Google Play Store Beschreibung
--------------------------------
Sichere Bitcoins zu eigenen Bedingungen, mit einem quelloffenen Gemeinschaftswallet(elektronische Brieftasche mit Mehrfachunterschriften) von BitPay.
Copay Nutzer können ihre Beträge individuell speichern oder ihre Finanzen mit anderen Nutzern in Gemeinschaftswallets teilen, die je nach Einstellung mehrere Bestätigungen (elektronische Unterschriften) benötigen und so nichtautorisierte Zahlungen verhindern.
Ein paar Einsatzmöglichkeiten, wie ein solches Wallet mit anderen Copayern genutzt werden kann:
Sichere Bitcoins zu eigenen Bedingungen, mit einem quelloffenen Gemeinschaftswallet (elektronische Brieftasche mit Mehrfachunterschriften) von BitPay.
Copay Nutzer können ihre Beträge individuell speichern oder ihre Finanzen mit anderen Nutzern in Gemeinschaftswallets teilen, die je nach Einstellung mehrere Bestätigungen (elektronische Unterschriften) benötigen und so nichtautorisierte Zahlungen verhindern. Ein paar Einsatzmöglichkeiten, wie ein solches Wallet mit anderen Copayern genutzt werden kann:
Ansparen von Beträgen für Urlaub oder gemeinsame Anschaffungen (z.B. mit Freunden)
Ansparen von Beträgen für Urlaub oder gemeinsame Anschaffungen (z.B. mit Freunden)
Überwachung von Ausgaben und Einkünften der Familie
Organisation der Ausgaben in Firmen, Vereinen oder Organisationen
Folgende Funktionen wurden in diese Version von Copay eingebaut um ein Bitcoin Wallet anzubieten das keine Kompromisse in Sichereit oder Zugänglichkeit eingeht:
Anlage und Verwaltung von mehreren Wallets innerhalb der Anwendung
Intiutive mehrfachunterschriften Sicherheit für persönliche und geteilete Wallets
Anlage und Verwaltung von mehreren Wallets innerhalb der Anwendung
Intiutive mehrfachunterschriften Sicherheit für persönliche und geteilete Wallets
Einfache Ausgabenvorschläge für geteilte Walltes und Gruppenzahlungen
Hierarchische deterministische(HD) Adresserzeugung und Sicherung der Wallets
Hierarchische deterministische(HD) Adresserzeugung und Sicherung der Wallets
Gerätebasierte Sicherheit: Alle privaten Schlüssel werden auf dem Gerät und nicht in der Cloud gespreichert
Unterstützung von Bitcoin Testnet Wallets
Gleichzeitiger Zugriff über alle wichtigen mobilen Systeme und Desktop-Plattformen
@ -24,19 +20,4 @@ E-Mail Benachrichtigung für Zahlungen und Transaktionen
Anpasspare Wallets: Eigene Namen und Hintergrundfarben
6 unterstützte Sprachen (deutsch, englisch, spanisch, französisch, japanisch, portugiesisch)
Copay ist eine kostenlose und quelloffene Software, die auf nicht firmeneigenen Servern läuft und es somit nicht nötig ist, sich auf ein bestimmtes Unternehmen und dessen kontinuierliche Unterstützung zu verlassen. Jeder hat die Möglichkeit den Quelltext zu überprüfen oder auf GitHub (https://github.com/bitpay/copay) eigene Änderungen beizutragen und an der Weiterentwicklung mitzuwirken.
--------------------------------
Google Play Store Release Notes: "What's new"
--------------------------------
v1.0.2
--------------------------------
Nach achtmonatigem Test hat Copay die Betaphase verlassen!
--------------------------------
v1.0.1
--------------------------------
Besserer Umgang mit Fehlern durch Netzwerkunterbrechungen
Bessere Logik nach Akzeptanz oder Ablehung von Zahlungen
Aktualisierung von ES, FR and JP Übersetzungen
Korrektur der Scroll-/Blätterfunktion in einigen Popups
--------------------------------
Copay ist eine kostenlose und quelloffene Software, die auf nicht firmeneigenen Servern läuft und es somit nicht nötig ist, sich auf ein bestimmtes Unternehmen und dessen kontinuierliche Unterstützung zu verlassen. Jeder hat die Möglichkeit den Quelltext zu überprüfen oder auf GitHub (https://github.com/bitpay/copay) eigene Änderungen beizutragen und an der Weiterentwicklung mitzuwirken.

23
i18n/docs/appstore_el.txt Normal file
View File

@ -0,0 +1,23 @@
Εξασφαλίστε τα Bitcoin σας με τους δικούς σας όρους με ένα ανοιχτού κώδικα, πορτοφόλι πολλών υπογραφών από την BitPay.
Οι χρήστες copay μπορούν να κρατούν και να διαχειρίζονται κεφάλαια ατομικά ή να τα μοιράζονται με ασφάλεια με άλλους χρήστες με το πορτοφόλι πολλών υπογραφών, το οποίο εμποδίζει τις μη εξουσιοδοτημένες πληρωμές και απαιτεί πολλαπλές εγκρίσεις. Εδώ είναι μερικοί τρόποι με τους οποίους το copay μπορεί να χρησιμοποιηθεί σε συνδιασμό με άλλους ανθρώπους:
Για να αποθηκεύσετε για τις διακοπές σας ή να κάνετε κοινές αγορές με τους φίλους σας
Για να παρακολουθήσετε τις οικογενειακές δαπάνες και τα επιδόμάτα
Για τη διαχείριση επιχειρήσεων, κλαμπ, ή κεφάλαια οργανισμών και έξοδα οργάνωσης
Χτίσαμε τα ακόλουθα χαρακτηριστικά σε αυτή την έκδοση του copay για ένα πορτοφόλι Bitcoin που δεν θέτει σε κίνδυνο την ασφάλεια ή την προσβασιμότητα:
Δημιουργία πολλαπλών πορτοφολιών και διαχείριση εντός εφαρμογής
Διαισθητική ασφαλείας πολλών υπογραφών για προσωπικά ή κοινόχρηστα πορτοφόλια
Εύκολη ροή προτάσεων δαπάνών για κοινόχρηστα πορτοφόλια και πληρωμές ομάδων
Ιεραρχική ντετερμινιστική δημιουργία διευθύνσεων (HD) και αντιγράφων ασφαλείας πορτοφολιού
Ασφάλεια με βάση τη συσκευή: όλα τα ιδιωτικά κλειδιά αποθηκεύονται τοπικά, όχι στο σύννεφο
Υποστήριξη για πορτοφόλια του δοκιμαστικού δικτύου Bitcoin
Σύγχρονισμένη πρόσβαση σε όλες τις μεγάλες πλατφόρμες, φορητές και επιτραπέζιες
Πρωτόκολλο πληρωμής (BIP70-BIP73) το οποίο υποστηρίζει: εύκολα αναγνωρίσιμες αιτήσεις πληρωμής και διασφάλισμένες και επαληθεύσιμες πληρωμές με Bitcoin
Υποστήριξη για επιλογές τιμολόγησης 150+ νομισμάτων και ονομαστική αξία σε BTC ή bits
Ειδοποιήσεις μέσω email για πληρωμές και μεταφορές
Προσαρμόσιμο όνομα πορτοφολιών και χρώματα φόντου
4 υποστηριζόμενες γλώσσες (Αγγλικά, Ιαπωνικά, Γαλλικά, Ισπανικά)
Το Copay είναι ελεύθερο και ανοικτού κώδικα λογισμικό το οποίο τρέχει σε μη ιδιόκτητους διακομιστές, έτσι δεν υπάρχει καμία ανάγκη να στηριχθεί σε οποιαδήποτε εταιρεία για να έχει συνεχή υποστήριξη. Ο καθένας μπορεί να αναθεωρήσει ή να συμβάλει στον πηγαίο κώδικα του copay στο GitHub (https://github.com/bitpay/copay).

View File

@ -1,6 +1,3 @@
--------------------------------
Google Play store description
--------------------------------
Secure bitcoin on your own terms with an open source, multisignature wallet from BitPay.
Copay users can hold funds individually or share finances securely with other users with multisignature wallets, which prevent unauthorized payments by requiring multiple approvals. Here are some ways Copay can be used with others:
@ -24,28 +21,3 @@ Customizable wallet naming and background colors
4 supported languages (EN, JP, FR, ES)
Copay is free and open source software run on non-proprietary servers, so there's no need to rely on any company for continuous support. Anyone can review or contribute to Copay's source code on GitHub (https://github.com/bitpay/copay).
--------------------------------
Google Play store Release Notes: "What's new"
--------------------------------
v1.1.0
--------------------------------
QR Codes with specified amount for Receiving Payments
Fund Transfer Between Wallets
HTML Email Notifications
Custom Transaction Fee Settings
Send Maximum Amount of Funds
New Spending Proposal Deletion Rules
Bugs Fixes for Offline Functionality
--------------------------------
v1.0.2
--------------------------------
Copay is now out of beta! We've spent eight months testing Copay, and we're production-ready.
--------------------------------
v1.0.1
--------------------------------
Better handling of network interruption errors
Better refresh logic after accepting/rejecting payments
Updates ES, JP and FR translations
Fix scroll with in certain popups
--------------------------------

View File

@ -1,42 +1,23 @@
--------------------------------
Google Play store description
--------------------------------
Asegura tus bitcoin con tus propias reglas con el monedero de código abierto, multifirma de BitPay.
Asegura tus bitcoin con tus propias reglas con el monedero de código abierto, multifirma de BitPay.
Los usuario de Copay pueden mantener sus fondos individuales o compartir sus finanzas de forma segura con otros usuarios utilizando monederos multifirmas, que previenen de pagos sin autorización al requerir múltiples aprobaciones. Estas son algunas formas en que puede ser utilizado Copay con otros usuarios:
Ahorrar para vacaciones o compras conjuntas con amigos
Ahorrar para vacaciones o compras conjuntas con amigos
Controlar los gastos familiares
Manejar los fondos y gastos de negocios, clubes y organizaciones.
Construimos las siguientes características en esta versión de Copay que no compromete la seguridad ni la accesibilidad:
Creación y manejo de múltiples monederos dentro de la misma aplicación
Creación y manejo de múltiples monederos dentro de la misma aplicación
Seguridad multifirma intuitiva para monederos personales y compartidos
Sencillo flujo de propuesta de gastos para monederos compartidos y grupos de pagos
Generación de direcciones HD (Hierarchical deterministic) y copias de seguridad
Generación de direcciones HD (Hierarchical deterministic) y copias de seguridad
Seguridad basada en el dispositivo: todas las claves privadas se guardan localmente, no en la nube
Soporta monederos bitcoin en testnet
Acceso sincrónico desde las principales plataformas móviles y de escritorio
Acceso sincrónico desde las principales plataformas móviles y de escritorio
Soporte al protocolo de pago (BIP70-BIP73): solicitudes de pagos fácilmente identificable y verificables como pago seguro en bitcoin
Soporte a más de 150 precios de monedas y unidades de denominación en BTC o bits
Notificaciones por email de pagos y transferencias
Monederos con nombres y colores de fondo personalizables
4 idiomas soportados (EN, JP, FR, ES)
Copay es un software gratuito y de código abierto que funciona en servidores no-propietarios, por lo que no es necesario confiar en una empresa para soporte continuo. Cualquier persona puede revisar y contribuir al código fuente de Copay en GitHub (https://github.com/bitpay/copay).
--------------------------------
Google Play store Release Notes: "What's new"
--------------------------------
v1.0.2
--------------------------------
¡Copay esta fuera de beta! Estuvimos ocho meses probando Copay, y ahora estamos listos en producción.
--------------------------------
v1.0.1
--------------------------------
Mejor manejo de errores en interrupciones de la red
Mejor lógica de actualización luego de aceptar/rechazar pagos
Actualiza traducciones en ES, JR y FR.
Corrige el desplazamiento en algunas ventanas emergentes
--------------------------------
Copay es un software gratuito y de código abierto que funciona en servidores no-propietarios, por lo que no es necesario confiar en una empresa para soporte continuo. Cualquier persona puede revisar y contribuir al código fuente de Copay en GitHub (https://github.com/bitpay/copay).

View File

@ -1,20 +1,16 @@
--------------------------------
Google Play store description
--------------------------------
Sécurisez vos bitcoins selon vos conditions avec un portefeuille open source et multi-signatures par BitPay.
Les utilisateurs de Copay peuvent détenir leurs fonds de manière individuelle, ou partager leurs finances de manière sécurisée avec les autres utilisateurs en utilisant des portefeuilles multi-signatures, ce qui empêche les paiements non autorisés en exigeant des approbations multiples.
Voici quelques exemples d'utilisation que vous pouvez avoir avec Copay et avec d'autres utilisateurs :
Les utilisateurs de Copay peuvent détenir leurs fonds de manière individuelle, ou partager leurs finances de manière sécurisée avec les autres utilisateurs en utilisant des portefeuilles multi-signatures, ce qui empêche les paiements non autorisés en exigeant des approbations multiples. Voici quelques exemples d'utilisation que vous pouvez avoir avec Copay et avec d'autres utilisateurs :
• Économiser pour des vacances ou partager des frais avec des amis.
• Économiser pour des vacances ou partager des frais avec des amis.
• Suivre des dépenses et remboursements familiaux.
• Gérer des fonds et des dépenses pour une entreprise, un club ou une organisation.
Nous avons développé les fonctionnalités suivantes dans cette version de Copay pour un portefeuille bitcoin qui ne fait pas de compromis sur la sécurité ou sur l'accessibilité :
• Création et gestion de portefeuilles multiples.
• Création et gestion de portefeuilles multiples.
• Sécurité de multi-signatures intuitive pour les portefeuilles personnels ou partagés.
• Demande de paiement facile pour les portefeuilles partagés et pour les paiements de groupe.
• Génération d'adresse déterministe hiérarchique (HD) et sauvegardes de portefeuilles.
• Génération d'adresse déterministe hiérarchique (HD) et sauvegardes de portefeuilles.
• Sécurité basée sur l'appareil : toutes les clés privées sont stockées localement, pas dans le cloud.
• Prise en charge des portefeuilles bitcoin testnet.
• Accès synchrone sur toutes les principales plateformes mobiles et de bureau.
@ -25,28 +21,3 @@ Nous avons développé les fonctionnalités suivantes dans cette version de Copa
• 4 langues prises en charge (EN, JP, FR, ES).
Copay est un logiciel gratuit et open source qui tourne sur des serveurs non-propriétaires, il n'y a donc pas besoin de compter sur une entreprise pour un support continuel. N'importe qui peut examiner ou contribuer au code source de Copay sur GitHub (https://github.com/bitpay/copay).
--------------------------------
Google Play store Release Notes: "What's new"
--------------------------------
v1.1.0
--------------------------------
• Code QR avec montant personnalisable pour recevoir des paiements.
• Transfert de fonds entre portefeuilles.
• Notifications e-mail HTML.
• Frais de transactions personnalisables.
• Possibilité d'envoyer le montant maximal des fonds disponibles.
• Nouvelles règles de suppression des propositions de dépenses.
• Corrections de bugs pour les fonctionnalités hors ligne.
--------------------------------
v1.0.2
--------------------------------
Copay est sorti de sa phase beta ! Nous avons passé huit mois à tester Copay, et nous sommes prêts pour sa mise en production.
--------------------------------
v1.0.1
--------------------------------
Meilleur traitement des erreurs d'interruption réseau
Meilleure logique de rafraichissement après l'acceptation/le rejet de paiements
Mise à jour des traductions ES, JP et FR
Corrige le défilement dans certaines pop-ups
--------------------------------

23
i18n/docs/appstore_it.txt Normal file
View File

@ -0,0 +1,23 @@
Metti al sicuro i tuoi bitcoins, alle tue condizioni, con un portafoglio open source e multifirma realizzato da BitPay.
Gli utenti Copay possono gestire i propri fondi individualmente, o condividerli in maniera sicura con altri utenti grazie ai portafogli multifirma, che prevengono pagamenti non autorizzati richiedendo più approvazioni. Ecco alcuni modi per utilizzare Copay con altre persone:
Per rismarmiare soldi per le vacanze o per acquisti congiunti con gli amici
Per tenere traccia di spese familiari o indennità
Per gestire i fondi e le spese di aziende, club, or organizzazioni
In questa versione di Copay abbiamo realizzato le seguenti funzioni per un portafoglio bitcoin che non comprometta sicurezza o accessibilità:
Creazione e gestione integrata di portafogli multipli
Sicurezza multifirma intuitiva per portafogli personali o condivisi
Proposte di pagamento facili da iniziare per portafogli condivisi e pagamenti di gruppo
Generazione di portafogli gerarchici deterministici (HD) e funzionalità di backup
Sicurezza integrata nel dispositivo: tutte le chiave private sono memorizzate localmente, non nel cloud
Supporto per portafogli della testnet Bitcoin
Accesso sincrono in tutte le piattaforme mobile e desktop
Supporto per il protocollo di pagamento (BIP70-BIP73): richieste di pagamento facilmente identificabili e pagamenti bitcoin sicuri e verificabili
Supporto per 150+ valute e denominazione in BTC o bits
Notifiche email per pagamenti o trasferimenti
Colori di sfondo e nomi dei portafogli personalizzabli
4 lingue supportate (EN, JP, FR, ES)
Copay è un software gratuito e open source che non dipende da server proprietari, pertanto il supporto del software non dipende da nessuna azienda. Chiunque può rivedere o contribuire al codice sorgente di Copay su GitHub (https://github.com/bitpay/copay).

View File

@ -1,20 +1,16 @@
--------------------------------
Google Play store description
--------------------------------
ビットコインにおける高度なセキュリティーを手軽に扱えるオープンソースマルチシグネチャウォレットです。
Copayは個人のご利用はもちろんのこと、複数人によるウォレット管理の権限分散も簡単なウォレットソフトを通してご活用いただけます。
ビットコインにおける高度なセキュリティーを手軽に扱えるオープンソースマルチシグネチャウォレットです。
Copayは個人のご利用はもちろんのこと、複数人によるウォレット管理の権限分散も簡単なウォレットソフトを通してご活用いただけます。 例えば:
例えば:
友達との旅行や買い物のために透明性抜群の環境で貯蓄したい時
友達との旅行や買い物のために透明性抜群の環境で貯蓄したい時
家族のお小遣いや日常の家計簿管理がしたい時
ビジネス・クラブ・団体の資金や財産管理を透明な管理分散がしたい時
下記の機能でセキュリティーも利便性も妥協しない最高のウォレットをCopayでご提供させていただきました
■ 複数のウォレットの作成・管理がアプリ内で管理可能
■ 複数のウォレットの作成・管理がアプリ内で管理可能
■ マルチシグネチャのウォレット分散管理でも個人ウォレットでも使いやすさ抜群
■ 送金の提案・承認・却下の流れが非常に直感的で分散管理が簡単
■ 階級的決定性ウォレット(HDウォレット)でアドレス生成とバックアップ管理をしているためバックアップは永久に各参加者1回ずつのみ
■ 階級的決定性ウォレット(HDウォレット)でアドレス生成とバックアップ管理をしているためバックアップは永久に各参加者1回ずつのみ
■ 端末に依存するセキュリティー、秘密鍵が全て端末に保管され、サーバに送ることは無い
■ ビットコインの開発テスト用ネットワークにも対応
■ メジャーなプラットフォーム全てに対応 (Windows, Mac, Linux, Android, iPhone, Windows Phone)
@ -24,29 +20,4 @@ Copayは個人のご利用はもちろんのこと、複数人によるウォレ
■ ウォレットごとの背景色設定や通称設定も可能でカスタマイズ性抜群
■ 4ヶ国語に対応 (英日仏西)
Copayは永久無料でオープンソースのソフトです。サーバーもオープンソースなので、独自運用や法人の利用やソース流用は許可します。ソースをご覧の際に間違いなどが見つかった場合、Githubにてご報告・ソース修正のプルリクエストなどをお願いします。(https://github.com/bitpay/copay)
--------------------------------
Google Play store Release Notes: "What's new"
--------------------------------
v1.1.0
--------------------------------
■ QRコードによる指定額の受取要請。
■ ウォレット間の送金が円滑に。
■ メール通知のHTML化。
■ ビットコインネットワーク手数料が指定可能に。
■ ボタン一つで全残高を一気に送金が可能に。
■ 送金の提案の取下げ条件の変更。
■ オフライン機能のバグ修正。
--------------------------------
v1.0.2
--------------------------------
Copayがようやくベータ版を抜けてリリース版になりました 8ヶ月の時間を掛けて品質テストしてきたので、皆さんに安全に使っていただけるようになりました
--------------------------------
v1.0.1
--------------------------------
ネットワーク接続エラーの処理改善
送金の提案を承諾・却下した後の更新ロジックを改善
スペイン語、日本語、フランス語の翻訳を更新
特定のポップアップにおけるスクロール問題を改善
--------------------------------
Copayは永久無料でオープンソースのソフトです。サーバーもオープンソースなので、独自運用や法人の利用やソース流用は許可します。 ソースをご覧の際に間違いなどが見つかった場合、Githubにてご報告・ソース修正のプルリクエストなどをお願いします。(https://github.com/bitpay/copay)

23
i18n/docs/appstore_ko.txt Normal file
View File

@ -0,0 +1,23 @@
비트코인을 당신이 원하는 방식으로 안전하게 보관할 수 있는 오픈소스 다중서명 지갑이 BitPay에서 출시됐습니다.
Copay는 사용자의 개인적인 자금 보관은 물론이고, 여러 명의 동의가 필요한 다중서명 지갑을 통해 누군가 독단적으로 자금을 써버리는 일을 방지하고 여럿이 함께 자금을 관리 할 수 있습니다. 예를 들면 이런 식으로 사용할 수 있습니다:
친구들과 함께 휴가를 떠나거나 공동구매를 하기 위해 돈을 모을 때
가족의 소비와 지출을 관리하고 싶을 때
사업, 동호회, 단체의 자금과 소비를 관리 하고 싶을 때
이번 버전 Copay는 안전과 접근성에 대해 타협하지 않는 비트코인 지갑이 되기 위해 다음과 같은 기능이 포함돼 있습니다
앱 안에서 가능한 여러 개의 지갑 생성과 관리
개인, 공유 지갑을 위한 직관적인 다중서명 안전장치
공유 지갑과 공동지불을 위해 손쉽게 가능한 지불제안
계층결정론적(Hierarchical deterministic, HD) 주소 생성과 지갑 백업
장치기반 보안: 모든 비밀키는 클라우드가 아닌 장치 내부에 보관됩니다
비트코인 테스트넷 지갑 지원
모든 주요 모바일, 데스크탑 플랫폼에서의 동시 접속을 지원합니다
Payment protocol (BIP70-BIP73)지원: 쉽게 확인 가능한 지불요청과 증명 가능한 비트코인 안전 결제
150가지가 넘는 통화 지원과 BTC와 bits의 단위 지원
지불, 송금의 이메일 알림
바꿀 수 있는 지갑의 이름과 배경색
4개국어 지원(영어, 일본어, 프랑스어, 스페인어)
Copay는 누구나 운영할 수 있는 서버에서 돌아가는 무료 오픈소스 소프트웨어입니다. 그러므로 어떤 한 회사의 지속적인 지원에 의지할 필요가 없습니다. 누구나 GitHub(https://github.com/bitpay/copay)에서 Copay의 소스코드를 검토하거나 참여할 수 있습니다

View File

@ -1,19 +1,16 @@
--------------------------------
Google Play store description
--------------------------------
Armazene bitcoin com seus próprios termos com uma carteira de multi-assinaturas, open source, do BitPay.
Usuários Copay podem manter fundos individualmente ou compartilhar finanças seguramente com outros usuários por meio de carteiras multi-assinadas, que previnem pagamentos não autorizados por meio de múltiplas aprovações. Algumas formas que a Copay pode ser usada com outros:
Para economizar para férias ou juntar compras com amigos
Para rastrear despesas familiares e To track family spending and descontos
Para economizar para férias ou juntar compras com amigos
Para rastrear despesas familiares e descontos
Para gerenciar negócios, clube ou organizar saldos e despesas
Nós construímos as seguintes funcionalidades nesta versão da Copay para uma carteira bitcoin que não comprometa segurança ou acessibilidade:
Criação de múltiplas carteiras com gerenciamento no aplicativo
Criação de múltiplas carteiras com gerenciamento no aplicativo
Segurança de multi-assinaturas intuitiva para carteiras pessoais ou compartilhadas
Fácil fluxo de propostas de gastos para carteiras compartilhadas e pagamentos agrupados
Geração de endereço Hierarchical deterministic (HD) e backups de carteiras
Geração de endereço Hierarchical deterministic (HD) e backups de carteiras
Segurança baseada em dispositivo: todas as chaves privadas são armazenadas localmente e não na nuvem
Suporte para carteiras de testes na Bitcoin testnet
Acesso síncrono entre todas as principais plataformas móveis e desktops
@ -23,19 +20,4 @@ Notificações por e-mail para pagamentos e transferências
Nomes e cores de fundo customizáveis para carteiras
5 idiomas suportados (EN, JP, FR, ES, PT-BR)
Copay é gratuito e um software livre rodando em servidores não-proprietários, que não precisa de nenhuma empresa para o suporte contínuo. Qualquer um pode revisar ou contribuir para o código-fonte da Copay no GitHub (https://github.com/bitpay/copay).
--------------------------------
Google Play store Release Notes: "What's new"
--------------------------------
v1.0.2
--------------------------------
Copay agora está fora do beta! Nós gastamos oito meses testando a Copay e estamos prontos para entrar em produção.
--------------------------------
v1.0.1
--------------------------------
Melhoria no tratamento de erros de interrupção de rede
Melhoria no lógica de renovação após aceitar/rejeitar pagamentos
Atualização das traduções para ES, JP e FR
Resolvida rolagem de certos popups
--------------------------------
Copay é gratuito e um software livre rodando em servidores não-proprietários, que não precisa de nenhuma empresa para o suporte contínuo. Qualquer um pode revisar ou contribuir para o código-fonte da Copay no GitHub (https://github.com/bitpay/copay).

23
i18n/docs/appstore_ru.txt Normal file
View File

@ -0,0 +1,23 @@
Обезопасьте биткойны на своих условиях с открытым исходным кодом, кошельком с мультиподписью от BitPay.
Пользователи Copay могут хранить средства самостоятельно или совместно безопасно управлять средствами вместе с другими пользователями с помощью кошельков с мультиподписью (multisignature wallets), которые предотвращают несанкционированный платежи, требуя несколько одобрений. Вот некоторые способы как Copay может быть использован вместе с другими пользователями:
Накопить на отпуск или совместные покупки с друзьями
Отслеживать семейные траты и карманные деньги
Управлять бизнесом, клубом, или средствами и расходами организации
Мы встроили следующие функции в эту версию Copay для биткойн-кошелька, которые не идут на компромисс безопасности или доступности:
Создание и управление множеством кошельков внутри приложения
Интуитивно-понятная безопасность, основанная на мультиподписи, для личных и общих кошельков
Удобный порядок предложений платежей для совместных кошельков и и групповых платежей
Генерирование иерархически-детерминированных (HD) адресов и бэкакоп кошельков
Безопасность на основе устройств: все закрытые ключи хранятся локально, а не в облаке
Поддержка кошельков Bitcoin testnet
Синхронный доступ со всех основных мобильных и настольных платформ
Поддержка платежных протоколов (BIP70-BIP73): легко идентифицируемые платежные запросы и проверяемо-безопасные биткойн-платежи
Поддержка отображения сумм в более чем 150 валютах и обозначение в BTC или bits
Уведомления о платежах и переводах по email
Настраиваемые названия кошельков и цветов фона
4 поддерживаемых языка (английский, японский, французский, испанский)
Copay бесплатен и является программным обеспечением с открытым исходным кодом, запускаемым на не-проприетарных серверах, поэтому нет необходимости полагаться на какую-либо компанию и её постоянную поддержку. Любой может просмотреть и сделать предложение по изменению исходного кода Copay на GitHub (https://github.com/bitpay/copay).

23
i18n/docs/appstore_tr.txt Normal file
View File

@ -0,0 +1,23 @@
Bitcoinlerinizi kendi kurallarınıza göre BitPay tarafından oluşturulan açık kaynak, çoklu imzalı bir cüzdan ile koruyun.
Copay kullanıcıları paralarını ayrı ayrı tutabilir veya çoklu imzalı cüzdanlar ile diğer kullanıcılarla arasında mali durumları paylaşabilirler ki birden fazla onay isteyen yetkilendirilmemiş ödemeleri önleyebilirler. Diğerleri ile kullanmak için bazı Copay yolları:
To save for vacations or joint purchases with friends
To track family spending and allowances
To manage business, club, or organization funds and expenses
We built the following features into this version of Copay for a bitcoin wallet that doesn't compromise on security or accessibility:
Multiple wallet creation and management in-app
Intuitive multisignature security for personal or shared wallets
Easy spending proposal flow for shared wallets and group payments
Hierarchical deterministic (HD) address generation and wallet backups
Device-based security: all private keys are stored locally, not in the cloud
Support for Bitcoin testnet wallets
Synchronous access across all major mobile and desktop platforms
Payment protocol (BIP70-BIP73) support: easily-identifiable payment requests and verifiably secure bitcoin payments
Support for 150+ currency pricing options and unit denomination in BTC or bits
Email notifications for payments and transfers
Customizable wallet naming and background colors
4 supported languages (EN, JP, FR, ES)
Copay is free and open source software run on non-proprietary servers, so there's no need to rely on any company for continuous support. Anyone can review or contribute to Copay's source code on GitHub (https://github.com/bitpay/copay).

23
i18n/docs/appstore_zh.txt Normal file
View File

@ -0,0 +1,23 @@
Secure bitcoin on your own terms with an open source, multisignature wallet from BitPay.
Copay users can hold funds individually or share finances securely with other users with multisignature wallets, which prevent unauthorized payments by requiring multiple approvals. Here are some ways Copay can be used with others:
To save for vacations or joint purchases with friends
To track family spending and allowances
可用来管理商务,团体,或集团的收支
We built the following features into this version of Copay for a bitcoin wallet that doesn't compromise on security or accessibility:
Multiple wallet creation and management in-app
Intuitive multisignature security for personal or shared wallets
Easy spending proposal flow for shared wallets and group payments
Hierarchical deterministic (HD) address generation and wallet backups
Device-based security: all private keys are stored locally, not in the cloud
Support for Bitcoin testnet wallets
Synchronous access across all major mobile and desktop platforms
Payment protocol (BIP70-BIP73) support: easily-identifiable payment requests and verifiably secure bitcoin payments
Support for 150+ currency pricing options and unit denomination in BTC or bits
Email notifications for payments and transfers
Customizable wallet naming and background colors
4种可用语言 (ENJPFRES)
Copay is free and open source software run on non-proprietary servers, so there's no need to rely on any company for continuous support. Anyone can review or contribute to Copay's source code on GitHub (https://github.com/bitpay/copay).

View File

@ -0,0 +1,5 @@
* Adaptive fee levels based on bitcoin network load
* Option to prevent creating transactions with unconfirmed inputs
* Added advanced sending options
* Added Italian, Russian, and Greek language options
* Kleinere Bug-Fixes

View File

@ -0,0 +1,5 @@
* Adaptive fee levels based on bitcoin network load
* Option to prevent creating transactions with unconfirmed inputs
* Added advanced sending options
* Added Italian, Russian, and Greek language options
* Μικρές διορθώσεις σφαλμάτων

View File

@ -0,0 +1,5 @@
* Adaptive fee levels based on bitcoin network load
* Option to prevent creating transactions with unconfirmed inputs
* Added advanced sending options
* Added Italian, Russian, and Greek language options
* Minor bug fixes

View File

@ -0,0 +1,5 @@
* Niveles de tasa adaptables en base a la carga de la red bitcoin
* Opción para evitar la creación de transacciones con entradas sin confirmar
* Opciones de envío avanzado
* Nuevos idiomas: Italiano, Ruso, and Griego
* Corrección de errores menores

View File

@ -0,0 +1,5 @@
* Les frais sont maintenant calculés dynamiquement, en fonction de la charge du réseau Bitcoin
* Ajout d'une option permettant d'éviter la création de transactions avec des entrées non confirmées
* Ajout d'options d'envois avancés
* Ajout de langues : Italien, Russe et Grec
* Corrections de bugs mineurs

View File

@ -0,0 +1,5 @@
* Livello della commissione basata sul carico del network bitcoin
* Opzione per impedire la creazione di transazioni con input non confermati
* Aggiunte le opzioni avanzate di invio
* Aggiunto il supporto alla lingua italiana, russa e greca
* Correzione bug minori

View File

@ -0,0 +1,5 @@
■ ネットワーク混雑状況に自動的に合わせる手数料設定
■ 未承認資金の使用を禁止するオプション
■ 詳細な送金設定の追加
■ イタリア語、ロシア語、ギリシャ語の言語選択を追加
■ バグの修正

View File

@ -0,0 +1,5 @@
* Adaptive fee levels based on bitcoin network load
* Option to prevent creating transactions with unconfirmed inputs
* Added advanced sending options
* Added Italian, Russian, and Greek language options
자잘한 버그 수정

View File

@ -0,0 +1,5 @@
* Adaptive fee levels based on bitcoin network load
* Option to prevent creating transactions with unconfirmed inputs
* Added advanced sending options
* Added Italian, Russian, and Greek language options
* Kleine bug fixes

View File

@ -0,0 +1,5 @@
* Адаптивные уровни комиссий на основе загрузки сети Bitcoin
* Опция, запрещающая создание транзакций с неподтверждёнными входами
* Добавлены расширенные настройки отправки
* Добавлены итальянский, русский и греческий языки
* Исправлены мелкие ошибки

View File

@ -0,0 +1,5 @@
* Bitcoin ağ yüküne göre daha uygun ücret düzeyleri
* Onaylanmamış girişler ile işlem oluşturmayı önlemek için tercih
* Gelişmiş gönderme seçenekleri eklendi
* İtalyanca, Rusça ve Yunanca dil seçenekleri eklendi
* Ufak hata düzeltmeleri

View File

@ -0,0 +1,5 @@
* Adaptive fee levels based on bitcoin network load
* Option to prevent creating transactions with unconfirmed inputs
* Added advanced sending options
* Added Italian, Russian, and Greek language options
*修复一些bug

File diff suppressed because it is too large Load Diff

1414
i18n/po/el.po Normal file

File diff suppressed because it is too large Load Diff

1414
i18n/po/es.po Normal file

File diff suppressed because it is too large Load Diff

View File

@ -2,24 +2,34 @@ msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Project-Id-Version: Copay\n"
"Project-Id-Version: copay\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: copay\n"
"X-Crowdin-Language: fr\n"
"X-Crowdin-File: template.pot\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Last-Translator: cmgustavo83\n"
"Language-Team: French\n"
"Language: fr\n"
"X-Generator: Poedit 1.6.10\n"
"PO-Revision-Date: 2015-08-14 02:33-0400\n"
#: public/views/walletHome.html
msgid "(possible double spend)"
msgstr "(double dépense éventuelle)"
#: public/views/modals/txp-details.html
msgid "* A payment proposal can be deleted if 1) you are the creator, and no other copayer has signed, or 2) 24 hours have passed since the proposal was created."
msgstr " Une proposition de transaction peut être supprimée si 1) vous êtes le créateur, et aucun des autres copayers n'a signé, ou 2) 24 heures sont passées depuis la création de la proposition."
msgstr "* Une proposition de paiement peut être supprimée si vous en êtes le créateur et qu'aucun des autres copayers n'a signé, ou si 24 heures sont passées depuis la création de la proposition."
#: public/views/backup.html
msgid "* You can safely install your backup on another device and use your wallet from multiple devices at the same time."
msgstr "Vous pouvez installer en toute sécurité votre sauvegarde sur un autre appareil et utiliser votre portefeuille depuis plusieurs appareils en même temps."
#: public/views/backup.html
msgid "A backup without its private key will allow the user to see the wallet balance, transactions, and create spend proposals. However, it will not be able to approve (sign) proposals."
msgstr "Une sauvegarde ne disposant pas de sa clé privée autorisera l'utilisateur à voir le solde du portefeuille, les transactions, et à créer des propositions de dépense. Cependant, il ne pourra pas approuver (signer) les propositions."
#: public/views/splash.html
msgid "A multisignature bitcoin wallet"
msgstr "Un portefeuille bitcoin multi-signatures"
@ -29,6 +39,9 @@ msgid "About Copay"
msgstr "À propos de Copay"
#: public/views/modals/txp-details.html
#: src/js/controllers/copayers.js
#: src/js/controllers/preferencesDelete.js
#: src/js/controllers/walletHome.js
msgid "Accept"
msgstr "Accepter"
@ -46,6 +59,10 @@ msgstr "Adresse"
msgid "Advanced"
msgstr "Avancés"
#: public/views/modals/advancedSend.html
msgid "Advanced Send"
msgstr "Envoi avancé"
#: public/views/disclaimer.html
msgid "Agree"
msgstr "Accepter"
@ -54,6 +71,10 @@ msgstr "Accepter"
msgid "Alias for <i>{{index.walletName}}</i>"
msgstr "Alias pour <i>{{index.walletName}}</i>"
#: public/views/translators.html
msgid "All contributions to Copay's translation are welcome. Sign up at crowdin.com and join the Copay project at"
msgstr "Toutes les contributions à la traduction de Copay sont les bienvenues. Inscrivez-vous sur crowdin.com et rejoignez le projet Copay sur"
#: public/views/splash.html
msgid "Already have a wallet?"
msgstr "Vous avez déjà un portefeuille ?"
@ -64,11 +85,15 @@ msgstr "Devise alternative"
#: public/views/paymentUri.html
#: public/views/walletHome.html
#: public/views/includes/output.html
#: public/views/modals/customized-amount.html
#: public/views/modals/txp-details.html
msgid "Amount"
msgstr "Montant"
#: src/js/services/bwsError.js
msgid "Amount below dust threshold"
msgstr "Montant en dessous du seuil minimal recommandé"
#: public/views/walletHome.html
#: public/views/modals/customized-amount.html
msgid "Amount in"
@ -87,6 +112,11 @@ msgstr "Êtes-vous certain de vouloir supprimer ce portefeuille ?"
msgid "Available Balance"
msgstr "Solde disponible"
#: public/views/preferencesFee.html
#: public/views/modals/advancedSend.html
msgid "Average confirmation time: {{fee.nbBlocks * 10}} minutes"
msgstr "Temps de confirmation moyen : {{fee.nbBlocks * 10}} minutes"
#: public/views/create.html
#: public/views/join.html
msgid "BIP32 master extended private key"
@ -114,13 +144,17 @@ msgstr "Sauvegarder"
msgid "Backup options"
msgstr "Options de sauvegarde"
#: src/js/services/profileService.js
msgid "Bad wallet invitation"
msgstr "Mauvaise invitation de portefeuille"
#: public/views/walletHome.html
msgid "Before receiving funds, it is highly recommended you backup your wallet keys."
msgstr "Avant de recevoir des fonds, il est fortement recommandé de sauvegarder les clés de votre portefeuille."
#: public/views/preferences.html
msgid "Bitcoin Network Fee Policy"
msgstr "Politique des frais de réseau Bitcoin"
msgstr "Stratégie des frais de réseau Bitcoin"
#: public/views/paymentUri.html
msgid "Bitcoin URI is NOT valid!"
@ -131,8 +165,8 @@ msgid "Bitcoin address"
msgstr "Adresse Bitcoin"
#: public/views/preferencesFee.html
msgid "Bitcoin transactions may include a fee collected by miners on the network. The higher the fee, the greater the incentive a miner has to include that transaction in a block. The Emergency level should only be used when there is a network congestion."
msgstr "Les transactions Bitcoin peuvent inclure des frais collectés par les mineurs du réseau. Plus les frais sont élevés, et plus l'incitation à inclure une transaction dans un bloc est importante pour les mineurs. La priorité "Urgente" ne devrait être utilisée que lorsque le réseau présente une congestion."
msgid "Bitcoin transactions may include a fee collected by miners on the network. The higher the fee, the greater the incentive a miner has to include that transaction in a block. Actual fees are determined based on network load and the selected policy."
msgstr "Les transactions Bitcoin peuvent inclure des frais prélevés par les mineurs sur le réseau. Plus les frais sont élevés, et plus un mineur sera incité à inclure cette transaction dans un bloc. Les frais actuels sont déterminés en fonction de la charge du réseau et de la stratégie sélectionnée."
#: public/views/modals/txp-details.html
msgid "Broadcast Payment"
@ -160,9 +194,17 @@ msgstr "ANNULER"
#: public/views/copayers.html
#: public/views/walletHome.html
#: public/views/modals/confirmation.html
#: src/js/controllers/copayers.js
#: src/js/controllers/preferencesDelete.js
#: src/js/controllers/walletHome.js
msgid "Cancel"
msgstr "Annuler"
#: src/js/services/profileService.js
msgid "Cannot join the same wallet more that once"
msgstr "Impossible de rejoindre le même portefeuille plus d'une fois"
#: public/views/modals/paypro.html
msgid "Certified by"
msgstr "Certifié par"
@ -171,10 +213,6 @@ msgstr "Certifié par"
msgid "Changing wallet alias only affects the local wallet name."
msgstr "La modification d'un alias de portefeuille affecte uniquement le nom du portefeuille local."
#: src/js/controllers/walletHome.js
msgid "Check you connection and try again"
msgstr "Vérifiez votre connexion internet et réessayez"
#: public/views/import.html
msgid "Choose a backup file from your computer"
msgstr "Choisissez un fichier de sauvegarde depuis votre ordinateur"
@ -184,6 +222,7 @@ msgid "Choose a wallet to send funds"
msgstr "Choisissez un portefeuille pour envoyer des fonds"
#: public/views/includes/topbar.html
#: public/views/modals/advancedSend.html
#: public/views/modals/copayers.html
#: public/views/modals/customized-amount.html
#: public/views/modals/paypro.html
@ -200,14 +239,42 @@ msgstr "Couleur"
msgid "Commit hash"
msgstr "Commit hash"
#: src/js/controllers/copayers.js
#: src/js/controllers/preferencesDelete.js
#: src/js/controllers/walletHome.js
msgid "Confirm"
msgstr "Confirmer"
#: public/views/modals/tx-details.html
msgid "Confirmations"
msgstr "Confirmations"
#: src/js/services/bwsError.js
msgid "Copayer already in this wallet"
msgstr "Copayer déjà dans ce portefeuille"
#: src/js/services/bwsError.js
msgid "Copayer already registered"
msgstr "Copayer déjà inscrit"
#: src/js/services/bwsError.js
msgid "Copayer already voted on this spend proposal"
msgstr "Le Copayer a déjà voté pour cette proposition de dépense"
#: src/js/services/bwsError.js
msgid "Copayer data mismatch"
msgstr "Les données Copayer ne correspondent pas"
#: public/views/modals/copayers.html
msgid "Copayers"
msgstr "Copayers"
#: src/js/controllers/backup.js
#: src/js/controllers/copayers.js
#: src/js/controllers/walletHome.js
msgid "Copied to clipboard"
msgstr "Copié dans le presse-papier"
#: public/views/backup.html
msgid "Copy backup to a safe place"
msgstr "Copiez la sauvegarde vers un endroit sûr"
@ -216,25 +283,25 @@ msgstr "Copiez la sauvegarde vers un endroit sûr"
msgid "Copy this text as it is to a safe place (notepad or email)"
msgstr "Copiez ce texte présenté tel quel vers un endroit sûr (bloc-notes ou e-mail)"
#: public/views/backup.html
#: public/views/backup.html
msgid "Copy to clipboard"
msgstr "Copier dans le presse-papier"
#: src/js/controllers/walletHome.js
msgid "Could not accept payment. Check you connection and try again"
msgstr "Impossible d'accepter le paiement. Vérifiez votre connexion internet et réessayez"
msgid "Could not accept payment"
msgstr "Impossible d'accepter le paiement"
#: src/js/controllers/index.js
msgid "Could not access Wallet Service: Not found"
msgstr "Impossible d'accéder au Wallet Service : Introuvable"
#: src/js/controllers/walletHome.js
msgid "Could not broadcast payment. Check you connection and try again"
msgstr "Impossible de diffuser le paiement. Vérifiez votre connexion internet et réessayez"
msgid "Could not broadcast payment"
msgstr "Impossible de diffuser le paiement"
#: src/js/controllers/walletHome.js
msgid "Could not connect wallet service. Check your Internet connexion and your wallet service configuration."
msgstr "Impossible de se connecter au service de portefeuille. Vérifiez votre connexion Internet et la configuration de votre service de portefeuille."
#: src/js/controllers/walletHome.js
msgid "Could not create address. Check you connection and try again"
msgstr "Impossible de créer l'adresse. Vérifiez votre connexion internet et réessayez"
#: src/js/services/addressService.js
msgid "Could not create address"
msgstr "Impossible de créer l'adresse"
#: src/js/controllers/walletHome.js
msgid "Could not create payment proposal"
@ -249,8 +316,8 @@ msgid "Could not decrypt file, check your password"
msgstr "Impossible de déchiffrer le fichier, vérifiez votre mot de passe"
#: src/js/controllers/walletHome.js
msgid "Could not delete payment proposal. Check you connection and try again"
msgstr "Impossible de supprimer la proposition de paiement. Vérifiez votre connexion internet et réessayez"
msgid "Could not delete payment proposal"
msgstr "Impossible de supprimer la proposition de paiement"
#: src/js/controllers/walletHome.js
msgid "Could not fetch payment information"
@ -266,21 +333,25 @@ msgstr "Impossible d'importer. Vérifiez le fichier d'entrée et le mot de passe
#: src/js/services/profileService.js
msgid "Could not join using the specified extended private key"
msgstr ""
msgstr "Impossible de rejoindre en utilisant la clé privée étendue spécifiée"
#: src/js/controllers/join.js
msgid "Could not join wallet:"
#: src/js/services/profileService.js
msgid "Could not join wallet"
msgstr "Impossible de rejoindre le portefeuille"
#: src/js/controllers/walletHome.js
msgid "Could not reject payment. Check you connection and try again"
msgstr "Impossible de rejeter le paiement. Vérifiez votre connexion internet réessayez"
msgid "Could not recognize a valid Bitcoin QR Code"
msgstr "Impossible de reconnaître un code QR Bitcoin valide"
#: src/js/controllers/walletHome.js
msgid "Could not reject payment"
msgstr "Impossible de rejeter le paiement"
#: src/js/controllers/walletHome.js
msgid "Could not send payment"
msgstr "Impossible d'envoyer le paiement"
#: public/views/walletHome.html
#: src/js/controllers/index.js
msgid "Could not update Wallet"
msgstr "Impossible de mettre à jour le portefeuille"
@ -309,7 +380,7 @@ msgstr "Créée par"
msgid "Creating Profile..."
msgstr "Création du profile..."
#: public/views/create.html
#: public/views/create.html
msgid "Creating Wallet..."
msgstr "Création du portefeuille..."
@ -317,6 +388,11 @@ msgstr "Création du portefeuille..."
msgid "Creating transaction"
msgstr "Création de la transaction"
#: public/views/preferencesFee.html
#: public/views/modals/advancedSend.html
msgid "Current fee rate for this policy: {{fee.feePerKBUnit}}/kiB"
msgstr "Frais actuels pour cette stratégie : {{fee.feePerKBUnit}}/kiB"
#: public/views/modals/tx-details.html
msgid "Date"
msgstr "Date"
@ -348,23 +424,27 @@ msgstr "Suppression du paiement"
msgid "Details"
msgstr "Détails"
#: src/js/controllers/index.js
msgid "Deutsch"
msgstr "Allemand"
#: public/views/preferences.html
msgid "Disabled"
msgstr "Désactivé"
#: public/views/backup.html
msgid "Do not include private key in backup"
msgstr "Ne pas inclure la clé privée dans la sauvegarde"
#: public/views/translators.html
msgid "Don't see your language on Crowdin? Contact the Owner on Crowdin! We'd love to support your language."
msgstr "Vous ne voyez pas votre langue sur Crowdin ? Contactez le propriétaire sur Crowdin ! Nous serions ravis de prendre en charge votre langue."
#: public/views/walletHome.html
msgid "Download CSV file"
msgstr "Télécharger le fichier CSV"
#: public/views/backup.html
msgid "Download backup"
msgstr "Télécharger la sauvegarde"
#: public/views/includes/password.html
msgid "ENTER"
msgstr "ENTRER"
#: src/js/controllers/preferencesFee.js
#: src/js/services/feeService.js
msgid "Economy"
msgstr "Économique"
@ -372,10 +452,6 @@ msgstr "Économique"
msgid "Email Notifications"
msgstr "Notifications e-mail"
#: src/js/controllers/preferencesFee.js
msgid "Emergency"
msgstr "Urgente"
#: public/views/preferences.html
msgid "Encrypt Private Key"
msgstr "Chiffrer la clé privée"
@ -384,22 +460,18 @@ msgstr "Chiffrer la clé privée"
msgid "Encrypted backup file saved"
msgstr "Le fichier de sauvegarde chiffré a été sauvegardé"
#: src/js/controllers/index.js
msgid "English"
msgstr "Anglais"
#: public/views/includes/password.html
msgid "Enter your password"
msgstr "Entrer votre mot de passe"
#: src/js/controllers/index.js
msgid "Error at Wallet Service"
msgstr "Erreur au niveau de Wallet Service"
#: src/js/services/profileService.js
msgid "Error creating wallet"
msgstr "Erreur de création du portefeuille"
#: src/js/services/profileService.js
msgid "Error creating wallet. Check your internet connection"
msgstr "Erreur de création du portefeuille. Vérifiez votre connexion internet"
#: src/js/services/profileService.js
msgid "Error importing wallet:"
msgstr "Erreur d'importation du portefeuille :"
@ -409,6 +481,10 @@ msgstr "Erreur d'importation du portefeuille :"
msgid "Expires"
msgstr "Expire"
#: public/views/backup.html
msgid "Failed to create backup"
msgstr "Impossible de créer la sauvegarde"
#: src/js/controllers/importLegacy.js
msgid "Failed to import wallets"
msgstr "Impossible d'importer les portefeuilles"
@ -417,19 +493,32 @@ msgstr "Impossible d'importer les portefeuilles"
msgid "Family vacation funds"
msgstr "Fonds pour les vacances familiales"
#: public/views/modals/tx-details.html
#: public/views/modals/txp-details.html
msgid "Fee"
msgstr "Frais"
#: public/views/modals/advancedSend.html
msgid "Fee Policy"
msgstr "Stratégie des frais"
#: public/views/walletHome.html
msgid "Fee policy for this transaction"
msgstr "Stratégie des frais pour cette transaction"
#. Get information of payment if using Payment Protocol
#: src/js/controllers/walletHome.js
msgid "Fetching Payment Information"
msgstr "Récupération des informations de paiement"
#: src/js/controllers/index.js
#: public/views/translators.html
msgid "French"
msgstr "Français"
#: src/js/services/bwsError.js
msgid "Funds are locked by pending spend proposals"
msgstr "Les fonds sont verrouillés par des propositions de dépenses en attente"
#: src/js/services/notificationsService.js
msgid "Funds received"
msgstr "Fonds reçus"
@ -446,6 +535,14 @@ msgstr "Générer un code QR"
msgid "Generate new address"
msgstr "Générer une nouvelle adresse"
#: public/views/walletHome.html
msgid "Generating .csv file..."
msgstr "Génération du fichier .csv..."
#: public/views/translators.html
msgid "German"
msgstr "Allemand"
#: public/views/modals/wallets.html
msgid "Getting address for wallet {{selectedWalletName}} ..."
msgstr "Obtention d'une adresse pour le portefeuille {{selectedWalletName}} ..."
@ -458,13 +555,19 @@ msgstr "Paramètres globaux"
msgid "Go back"
msgstr "Retour"
#: public/views/translators.html
msgid "Greek"
msgstr "Grec"
#: public/views/import.html
msgid "Have a Backup from Copay v0.9?"
msgstr "Vous avez une sauvegarde de Copay v0.9 ?"
#: public/views/create.html
#: public/views/backup.html
#: public/views/create.html
#: public/views/join.html
msgid "Hide Advanced options"
#: public/views/walletHome.html
msgid "Hide advanced options"
msgstr "Masquer les options avancées"
#: src/js/controllers/index.js
@ -513,11 +616,39 @@ msgstr "Importation du portefeuille..."
msgid "Importing..."
msgstr "Importation..."
#: src/js/controllers/index.js
#: src/js/services/bwsError.js
msgid "Incorrect address network"
msgstr "Adresse réseau incorrecte"
#: src/js/services/bwsError.js
msgid "Insufficient funds"
msgstr "Fonds insuffisants"
#: src/js/services/bwsError.js
msgid "Insufficient funds for fee"
msgstr "Fonds insuffisants pour les frais"
#: public/views/walletHome.html
msgid "Invalid"
msgstr "Invalide"
#: src/js/services/bwsError.js
msgid "Invalid address"
msgstr "Adresse invalide"
#: src/js/controllers/copayers.js
msgid "Invitation to share a Copay Wallet"
msgstr "Invitation pour partager un portefeuille Copay"
#: public/views/translators.html
msgid "Italian"
msgstr "Italien"
#: public/views/translators.html
msgid "Japanese"
msgstr "Japonais"
#: public/views/create.html
#: public/views/create.html
#: public/views/join.html
msgid "John"
msgstr "John"
@ -526,6 +657,10 @@ msgstr "John"
msgid "Join"
msgstr "Rejoindre"
#: src/js/controllers/copayers.js
msgid "Join my Copay wallet. Here is the invitation code: {{secret}} You can download Copay for your phone or desktop at https://copay.io"
msgstr "Rejoignez mon portefeuille Copay. Voici le code d'invitation : {{secret}} Vous pouvez télécharger Copay pour votre téléphone ou pour votre ordinateur sur https://copay.io"
#: public/views/add.html
msgid "Join shared wallet"
msgstr "Rejoindre"
@ -542,6 +677,14 @@ msgstr "Langue"
msgid "Learn more about Wallet Migration"
msgstr "En savoir plus sur la migration de portefeuille"
#: src/js/services/bwsError.js
msgid "Locktime in effect. Please wait to create a new spend proposal"
msgstr "Locktime effectif. Veuillez patienter pour créer une nouvelle proposition de dépense"
#: src/js/services/bwsError.js
msgid "Locktime in effect. Please wait to remove this spend proposal"
msgstr "Locktime effectif. Veuillez patienter pour supprimer cette proposition de dépense"
#: public/views/paymentUri.html
msgid "Make a payment to"
msgstr "Faire un paiement à"
@ -551,14 +694,17 @@ msgstr "Faire un paiement à"
msgid "Master extended private key"
msgstr "Clé privée étendue maîtresse"
#: public/views/includes/copayers.html
#: public/views/includes/copayers.html
#: public/views/modals/copayers.html
#: public/views/modals/tx-details.html
#: public/views/modals/txp-details.html
msgid "Me"
msgstr "Moi"
#: public/views/modals/paypro.html
#: public/views/modals/paypro.html
msgid "Memo"
msgstr "Note"
#: public/views/modals/tx-details.html
msgid "Merchant message"
msgstr "Message marchand"
@ -587,32 +733,45 @@ msgstr "Mon adresse Bitcoin"
msgid "Network"
msgstr "Réseau"
#: src/js/services/bwsError.js
msgid "Network connection error"
msgstr "Erreur de connexion réseau"
#: src/js/services/notificationsService.js
msgid "New Payment Proposal"
msgstr "Nouvelle proposition de paiement"
#: public/views/modals/confirmation.html
msgid "No"
msgstr "Non"
#: public/views/walletHome.html
msgid "No Private key"
msgstr "Aucune clé privée"
#: public/views/walletHome.html
msgid "No transactions yet"
msgstr "Aucune transaction"
#: src/js/controllers/preferencesFee.js
#: src/js/services/feeService.js
msgid "Normal"
msgstr "Normale"
#: src/js/services/bwsError.js
msgid "Not authorized"
msgstr "Non autorisé"
#: public/views/walletHome.html
#: public/views/modals/customized-amount.html
msgid "Not valid"
msgstr "Non valide"
#: public/views/walletHome.html
#: public/views/includes/output.html
#: public/views/modals/tx-details.html
#: public/views/modals/txp-details.html
msgid "Note:"
msgstr "Note :"
msgid "Note"
msgstr "Note"
#: public/views/includes/alert.html
#: public/views/includes/password.html
msgid "OK"
msgstr "Ok"
#: public/views/modals/tx-status.html
msgid "OKAY"
@ -623,7 +782,7 @@ msgstr "Ok"
msgid "Participants"
msgstr "Participants"
#: public/views/import.html
#: public/views/import.html
#: public/views/importLegacy.html
msgid "Password"
msgstr "Mot de passe"
@ -717,6 +876,10 @@ msgstr "Paiement envoyé !"
msgid "Payment to"
msgstr "Paiement à"
#: public/views/walletHome.html
msgid "Pending Confirmation"
msgstr "Confirmations en attente"
#: public/views/preferencesDeleteWallet.html
msgid "Permanently delete this wallet. THIS ACTION CANNOT BE REVERSED"
msgstr "Supprimer définitivement ce portefeuille. CETTE ACTION NE PEUT PAS ÊTRE ANNULÉE"
@ -730,11 +893,15 @@ msgstr "Portefeuille personnel"
msgid "Please enter the required fields"
msgstr "Veuillez saisir les champs requis"
#: src/js/services/bwsError.js
msgid "Please upgrade Copay to perform this action"
msgstr "Veuillez mettre à jour Copay pour effectuer cette action"
#: src/js/controllers/import.js
msgid "Please, select your backup file"
msgstr "Veuillez sélectionner votre fichier de sauvegarde"
#: src/js/controllers/index.js
#: public/views/translators.html
msgid "Portuguese"
msgstr "Portugais"
@ -742,7 +909,11 @@ msgstr "Portugais"
msgid "Preferences"
msgstr "Préférences"
#: src/js/controllers/preferencesFee.js
#: src/js/controllers/backup.js
msgid "Preparing backup..."
msgstr "Préparation de la sauvegarde..."
#: src/js/services/feeService.js
msgid "Priority"
msgstr "Prioritaire"
@ -762,6 +933,11 @@ msgstr "Recevoir"
msgid "Received"
msgstr "Reçue"
#: public/views/includes/output.html
#: public/views/includes/transaction.html
msgid "Recipients"
msgstr "Destinataires"
#: public/views/walletHome.html
msgid "Reconnecting to Wallet Service..."
msgstr "Reconnexion au service de portefeuille..."
@ -786,7 +962,7 @@ msgstr "Rejet du paiement"
msgid "Release Information"
msgstr "Informations de version"
#: public/views/backup.html
#: public/views/backup.html
#: public/views/includes/password.html
msgid "Repeat password"
msgstr "Répétez le mot de passe"
@ -796,7 +972,7 @@ msgstr "Répétez le mot de passe"
msgid "Request a specific amount"
msgstr "Demander un montant précis"
#: public/views/import.html
#: public/views/import.html
#: public/views/join.html
msgid "Required"
msgstr "Requis"
@ -805,6 +981,10 @@ msgstr "Requis"
msgid "Retrying..."
msgstr "Nouvelle tentative"
#: public/views/translators.html
msgid "Russian"
msgstr "Russe"
#: public/views/includes/password.html
msgid "SET"
msgstr "DEFINIR"
@ -918,10 +1098,16 @@ msgstr "Partagez cette adresse de portefeuille pour recevoir des paiements. Pour
msgid "Shared Wallet"
msgstr "Portefeuille partagé"
#: public/views/backup.html
#: public/views/create.html
#: public/views/join.html
msgid "Show Advanced options"
msgstr "Montrer les options avancées"
#: public/views/walletHome.html
msgid "Show advanced options"
msgstr "Afficher les options avancées"
#: src/js/services/bwsError.js
msgid "Signatures rejected by server"
msgstr "Signatures rejetées par le serveur"
#: src/js/controllers/walletHome.js
msgid "Signing payment"
@ -931,13 +1117,17 @@ msgstr "Signature du paiement"
msgid "Signing transaction"
msgstr "Signature de la transaction"
#: src/js/controllers/index.js
#: public/views/translators.html
msgid "Spanish"
msgstr "Espagnol"
#: public/views/walletHome.html
msgid "Spend proposals"
msgstr "Propositions de dépense"
#: src/js/services/bwsError.js
msgid "Spend proposal is not accepted"
msgstr "La proposition de dépense n'est pas acceptée"
#: src/js/services/bwsError.js
msgid "Spend proposal not found"
msgstr "Propostion de dépense introuvable"
#: src/js/controllers/copayers.js
#: src/js/controllers/import.js
@ -963,20 +1153,39 @@ msgid "The payment was created but could not be completed. Please try again from
msgstr "Le paiement a été créé mais n'a pas pu être achevé. Veuillez réessayer depuis l'écran d'accueil"
#: src/js/controllers/walletHome.js
msgid "The payment was created but could not be signed. Please try again from home screen."
msgid "The payment was created but could not be signed. Please try again from home screen"
msgstr "Le paiement a été créé mais n'a pas pu être signé. Veuillez réessayer depuis l'écran d'accueil"
#: public/views/modals/txp-details.html
msgid "The payment was removed by creator"
msgstr "Le paiement a été supprimé par le créateur"
#: src/js/controllers/walletHome.js
msgid "The payment was signed but could not be broadcasted. Please try again from home screen"
msgstr "Le paiement a été signé mais ne peut pas être diffusé. Veuillez réessayer depuis l'écran d'accueil"
#: public/views/backup.html
msgid "The private key for this wallet is encrypted. Exporting a backup will keep the private key encrypted in the backup archive."
msgstr "La clé privée pour ce portefeuille est chiffrée. Exporter une sauvegarde conservera le chiffrement de la clé dans l'archive de sauvegarde."
#: public/views/disclaimer.html
msgid "The software you are about to use functions as a free, open source, and multi-signature digital wallet. The software does not constitute an account where BitPay or other third parties serve as financial intermediaries or custodians of your bitcoin. While the software has undergone beta testing and continues to be improved by feedback from the open-source user and developer community, we cannot guarantee that there will be no bugs in the software. You acknowledge that your use of this software is at your own discretion and in compliance with all applicable laws. You are responsible for safekeeping your passwords, private key pairs, PINs and any other codes you use to access the software. IF YOU LOSE ACCESS TO YOUR COPAY WALLET OR YOUR ENCRYPTED PRIVATE KEYS AND YOU HAVE NOT SEPARATELY STORED A BACKUP OF YOUR WALLET AND CORRESPONDING PASSWORD, YOU ACKNOWLEDGE AND AGREE THAT ANY BITCOIN YOU HAVE ASSOCIATED WITH THAT COPAY WALLET WILL BECOME INACCESSIBLE. All transaction requests are irreversible. The authors of the software, employees and affiliates of Bitpay, copyright holders, and BitPay, Inc. cannot retrieve your private keys or passwords if you lose or forget them and cannot guarantee transaction confirmation as they do not have control over the Bitcoin network. To the fullest extent permitted by law, this software is provided “as is” and no representations or warranties can be made of any kind, express or implied, including but not limited to the warranties of merchantability, fitness or a particular purpose and noninfringement. You assume any and all risks associated with the use of the software. In no event shall the authors of the software, employees and affiliates of Bitpay, copyright holders, or BitPay, Inc. be held liable for any claim, damages or other liability, whether in an action of contract, tort, or otherwise, arising from, out of or in connection with the software. We reserve the right to modify this disclaimer from time to time."
msgstr "Le logiciel que vous êtes sur le point d'utiliser fonctionne comme un portefeuille numérique gratuit, open source et multi-signatures.\nLe logiciel ne constitue pas un compte où BitPay, ou des tiers, agissent comme des intermédiaires financiers ou dépositaires de vos bitcoins.\nBien que le logiciel ait subi des tests bêta et continue d'être amélioré par les commentaires d'utilisateurs et de développeurs de la communauté open source, nous ne pouvons pas garantir qu'il n'y aura plus de bugs dans le logiciel.\nVous reconnaissez que votre utilisation de ce logiciel est à votre propre discrétion et est en conformité avec toutes les lois applicables.\nVous êtes responsable de la sauvegarde de vos mots de passe, paires de clés privées, codes PIN et autres codes que vous utilisez pour accéder au logiciel.\nSI VOUS PERDEZ L'ACCÈS À VOTRE PORTEFEUILLE COPAY OU À VOS CLÉS PRIVÉES CHIFFRÉES ET QUE VOUS N'AVEZ PAS ENTREPOSÉ SÉPARÉMENT UNE SAUVEGARDE DE VOTRE PORTEFEUILLE ET LES MOTS DE PASSE CORRESPONDANT, VOUS RECONNAISSEZ ET ACCEPTEZ QUE LES BITCOINS QUE VOUS AVEZ ASSOCIÉ À CE PORTEFEUILLE COPAY DEVIENNENT INACCESSIBLES.\nToutes les transactions sont irréversibles.\nLes auteurs de ce logiciel, employés et sociétés affiliés à BitPay, détenteurs de droits d'auteur, et BitPay, Inc. ne peuvent pas récupérer vos clés privées ou mots de passe si vous les perdez et ne peuvent pas garantir la confirmation des transactions étant donné qu'ils n'ont pas de contrôle sur le réseau Bitcoin.\nDans toute la mesure permise par la loi, ce logiciel est fourni “tel quel” et aucune représentation ou garantie ne peut être faite de toute nature, expresse ou implicite, y compris, mais sans s'y limiter, les garanties de qualité marchande, la conformité ou un usage particulier et absent de contrefaçon.\nVous assumez tous les risques associés à l'utilisation du logiciel.\nEn aucun cas les auteurs des logiciels, employés et sociétés affiliés de Bitpay, détenteurs de droits d'auteur, ou BitPay, Inc. ne peuvent être tenus responsables de toute réclamation, dommages ou autre responsabilité, que ce soit dans une action contractuelle, délictuelle ou autre, découlant ou en étant en connexion avec le logiciel.\nNous nous réservons le droit de modifier cette clause de temps à autre."
msgstr "Le logiciel que vous êtes sur le point d'utiliser fonctionne comme un portefeuille numérique gratuit, open source et multi-signatures.\n"
"Le logiciel ne constitue pas un compte où BitPay, ou des tiers, agissent comme des intermédiaires financiers ou dépositaires de vos bitcoins.\n"
"Bien que le logiciel ait subi des tests bêta et continue d'être amélioré par les commentaires d'utilisateurs et de développeurs de la communauté open source, nous ne pouvons pas garantir qu'il n'y aura plus de bugs dans le logiciel.\n"
"Vous reconnaissez que votre utilisation de ce logiciel est à votre propre discrétion et est en conformité avec toutes les lois applicables.\n"
"Vous êtes responsable de la sauvegarde de vos mots de passe, paires de clés privées, codes PIN et autres codes que vous utilisez pour accéder au logiciel.\n"
"SI VOUS PERDEZ L'ACCÈS À VOTRE PORTEFEUILLE COPAY OU À VOS CLÉS PRIVÉES CHIFFRÉES ET QUE VOUS N'AVEZ PAS ENTREPOSÉ SÉPARÉMENT UNE SAUVEGARDE DE VOTRE PORTEFEUILLE ET LES MOTS DE PASSE CORRESPONDANT, VOUS RECONNAISSEZ ET ACCEPTEZ QUE LES BITCOINS QUE VOUS AVEZ ASSOCIÉ À CE PORTEFEUILLE COPAY DEVIENNENT INACCESSIBLES.\n"
"Toutes les transactions sont irréversibles.\n"
"Les auteurs de ce logiciel, employés et sociétés affiliés à BitPay, détenteurs de droits d'auteur, et BitPay, Inc. ne peuvent pas récupérer vos clés privées ou mots de passe si vous les perdez et ne peuvent pas garantir la confirmation des transactions étant donné qu'ils n'ont pas de contrôle sur le réseau Bitcoin.\n"
"Dans toute la mesure permise par la loi, ce logiciel est fourni “tel quel” et aucune représentation ou garantie ne peut être faite de toute nature, expresse ou implicite, y compris, mais sans s'y limiter, les garanties de qualité marchande, la conformité ou un usage particulier et absent de contrefaçon.\n"
"Vous assumez tous les risques associés à l'utilisation du logiciel.\n"
"En aucun cas les auteurs des logiciels, employés et sociétés affiliés de Bitpay, détenteurs de droits d'auteur, ou BitPay, Inc. ne peuvent être tenus responsables de toute réclamation, dommages ou autre responsabilité, que ce soit dans une action contractuelle, délictuelle ou autre, découlant ou en étant en connexion avec le logiciel.\n"
"Nous nous réservons le droit de modifier cette clause de temps à autre."
#: src/js/services/bwsError.js
msgid "The spend proposal is not pending"
msgstr "La proposition de dépense n'est pas en attente"
#: src/js/controllers/copayers.js
#: src/js/controllers/preferencesDelete.js
@ -991,21 +1200,30 @@ msgstr "Il n'y a pas de portefeuilles pour faire ce paiement"
msgid "There is an error in the form"
msgstr "Il y a une erreur dans la forme"
#: public/views/modals/tx-details.html
msgid "This transaction has become invalid; possibly due to a double spend attempt."
msgstr "Cette transaction est devenue invalide ; il s'agit peut-être d'une tentative de double dépense."
#: public/views/walletHome.html
msgid "This wallet is not registered at the given Bitcore Wallet Service (BWS). You can recreate it from the local information."
msgstr "Ce portefeuille n'est pas enregistré dans le Bitcore Wallet Service (BWS).Vous pouvez le recréer depuis l'information locale."
msgstr "Ce portefeuille n'est pas enregistré dans le Bitcore Wallet Service (BWS) donné. Vous pouvez le recréer depuis l'information locale."
#: public/views/modals/txp-details.html
msgid "Time"
msgstr "Heure"
msgstr "Ancienneté"
#: public/views/walletHome.html
#: public/views/includes/output.html
#: public/views/includes/transaction.html
#: public/views/modals/tx-details.html
#: public/views/modals/txp-details.html
msgid "To"
msgstr "À"
#: public/views/includes/output.html
msgid "Total"
msgstr "Total"
#: public/views/walletHome.html
msgid "Total Locked Balance"
msgstr "Solde verrouillé total"
@ -1014,11 +1232,23 @@ msgstr "Solde verrouillé total"
msgid "Transaction"
msgstr "Transaction"
#: src/js/services/bwsError.js
msgid "Transaction already broadcasted"
msgstr "Transaction déjà diffusée"
#: public/views/translators.html
msgid "Translation Credits"
msgstr "Crédits de traduction"
#: public/views/preferencesAbout.html
msgid "Translators"
msgstr "Traducteurs"
#: src/js/controllers/walletHome.js
msgid "Unable to send transaction proposal"
msgstr "Impossible d'envoyer la proposition de transaction"
#: public/views/walletHome.html
#: public/views/walletHome.html
#: public/views/modals/tx-details.html
msgid "Unconfirmed"
msgstr "Non confirmée"
@ -1039,6 +1269,11 @@ msgstr "Non-approuvé"
msgid "Updating Wallet..."
msgstr "Mise à jour du portefeuille..."
#: public/views/preferences.html
#: public/views/walletHome.html
msgid "Use Unconfirmed Funds"
msgstr "Utiliser les fonds non confirmés"
#: public/views/preferencesAbout.html
msgid "Version"
msgstr "Version"
@ -1083,6 +1318,7 @@ msgstr "Invitation de portefeuille"
msgid "Wallet Invitation is not valid!"
msgstr "L'invitation de portefeuille n'est pas valide !"
#: src/js/services/bwsError.js
#: src/js/services/profileService.js
msgid "Wallet already exists"
msgstr "Le portefeuille existe déjà"
@ -1091,18 +1327,34 @@ msgstr "Le portefeuille existe déjà"
msgid "Wallet incomplete and broken"
msgstr "Portefeuille incomplet et cassé "
#: src/js/services/bwsError.js
msgid "Wallet is full"
msgstr "Le portefeuille est plein"
#: src/js/services/bwsError.js
msgid "Wallet is not complete"
msgstr "Le portefeuille n'est pas complet"
#: public/views/create.html
msgid "Wallet name"
msgstr "Nom du portefeuille"
#: src/js/controllers/walletHome.js
msgid "Wallet service timed out. Check your Internet connexion and your wallet service configuration."
msgstr "Le service de portefeuille s'est déconnecté. Vérifiez votre connexion Internetet la configuration de votre service de portefeuille."
#: src/js/services/bwsError.js
msgid "Wallet not found"
msgstr "Portefeuille introuvable"
#: src/js/services/bwsError.js
msgid "Wallet service not found"
msgstr "Wallet Service introuvable"
#: public/views/preferencesDeleteWallet.html
msgid "Warning!"
msgstr "Attention !"
#: public/views/modals/txp-details.html
msgid "Warning: this transaction has unconfirmed inputs"
msgstr "ATTENTION : Cette transaction a des entrées non confirmées"
#: src/js/services/profileService.js
msgid "Wrong password"
msgstr "Mauvais mot de passe"
@ -1115,7 +1367,7 @@ msgstr "Oui"
msgid "You do not have a wallet"
msgstr "Vous n'avez aucun portefeuille"
#: public/views/backup.html
#: public/views/backup.html
#: public/views/import.html
msgid "Your backup password"
msgstr "Votre mot de passe de sauvegarde"
@ -1163,10 +1415,6 @@ msgstr "paramètres"
msgid "too long!"
msgstr "trop long !"
#: public/views/preferencesFee.html
msgid "{{fee.value}} bits per kB"
msgstr "{{fee.value}} bits par kB"
#: src/js/controllers/walletHome.js
msgid "{{fee}} will be discounted for bitcoin networking fees"
msgstr "{{fee}} seront déduits pour les frais de réseau Bitcoin"
@ -1174,3 +1422,4 @@ msgstr "{{fee}} seront déduits pour les frais de réseau Bitcoin"
#: src/js/controllers/importLegacy.js
msgid "{{len}} wallets imported. Funds scanning in progress. Hold on to see updated balance"
msgstr "{{len}} portefeuilles importés. L'analyse des fonds a démarré. Le solde va se mettre à jour"

1414
i18n/po/it.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1414
i18n/po/ko.po Normal file

File diff suppressed because it is too large Load Diff

1414
i18n/po/nl.po Normal file

File diff suppressed because it is too large Load Diff

1414
i18n/po/pt.po Normal file

File diff suppressed because it is too large Load Diff

1414
i18n/po/ru.po Normal file

File diff suppressed because it is too large Load Diff

1414
i18n/po/sq.po Normal file

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,10 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Project-Id-Version: \n"
#: public/views/walletHome.html
msgid "(possible double spend)"
msgstr ""
#: public/views/modals/txp-details.html
msgid "* A payment proposal can be deleted if 1) you are the creator, and no other copayer has signed, or 2) 24 hours have passed since the proposal was created."
msgstr ""
@ -12,6 +16,10 @@ msgstr ""
msgid "* You can safely install your backup on another device and use your wallet from multiple devices at the same time."
msgstr ""
#: public/views/backup.html
msgid "A backup without its private key will allow the user to see the wallet balance, transactions, and create spend proposals. However, it will not be able to approve (sign) proposals."
msgstr ""
#: public/views/splash.html
msgid "A multisignature bitcoin wallet"
msgstr ""
@ -21,6 +29,9 @@ msgid "About Copay"
msgstr ""
#: public/views/modals/txp-details.html
#: src/js/controllers/copayers.js
#: src/js/controllers/preferencesDelete.js
#: src/js/controllers/walletHome.js
msgid "Accept"
msgstr ""
@ -38,6 +49,10 @@ msgstr ""
msgid "Advanced"
msgstr ""
#: public/views/modals/advancedSend.html
msgid "Advanced Send"
msgstr ""
#: public/views/disclaimer.html
msgid "Agree"
msgstr ""
@ -46,6 +61,10 @@ msgstr ""
msgid "Alias for <i>{{index.walletName}}</i>"
msgstr ""
#: public/views/translators.html
msgid "All contributions to Copay's translation are welcome. Sign up at crowdin.com and join the Copay project at"
msgstr ""
#: public/views/splash.html
msgid "Already have a wallet?"
msgstr ""
@ -56,11 +75,15 @@ msgstr ""
#: public/views/paymentUri.html
#: public/views/walletHome.html
#: public/views/includes/output.html
#: public/views/modals/customized-amount.html
#: public/views/modals/txp-details.html
msgid "Amount"
msgstr ""
#: src/js/services/bwsError.js
msgid "Amount below dust threshold"
msgstr ""
#: public/views/walletHome.html
#: public/views/modals/customized-amount.html
msgid "Amount in"
@ -79,6 +102,11 @@ msgstr ""
msgid "Available Balance"
msgstr ""
#: public/views/preferencesFee.html
#: public/views/modals/advancedSend.html
msgid "Average confirmation time: {{fee.nbBlocks * 10}} minutes"
msgstr ""
#: public/views/create.html
#: public/views/join.html
msgid "BIP32 master extended private key"
@ -106,6 +134,10 @@ msgstr ""
msgid "Backup options"
msgstr ""
#: src/js/services/profileService.js
msgid "Bad wallet invitation"
msgstr ""
#: public/views/walletHome.html
msgid "Before receiving funds, it is highly recommended you backup your wallet keys."
msgstr ""
@ -123,7 +155,7 @@ msgid "Bitcoin address"
msgstr ""
#: public/views/preferencesFee.html
msgid "Bitcoin transactions may include a fee collected by miners on the network. The higher the fee, the greater the incentive a miner has to include that transaction in a block. The Emergency level should only be used when there is a network congestion."
msgid "Bitcoin transactions may include a fee collected by miners on the network. The higher the fee, the greater the incentive a miner has to include that transaction in a block. Actual fees are determined based on network load and the selected policy."
msgstr ""
#: public/views/modals/txp-details.html
@ -152,9 +184,17 @@ msgstr ""
#: public/views/copayers.html
#: public/views/walletHome.html
#: public/views/modals/confirmation.html
#: src/js/controllers/copayers.js
#: src/js/controllers/preferencesDelete.js
#: src/js/controllers/walletHome.js
msgid "Cancel"
msgstr ""
#: src/js/services/profileService.js
msgid "Cannot join the same wallet more that once"
msgstr ""
#: public/views/modals/paypro.html
msgid "Certified by"
msgstr ""
@ -163,10 +203,6 @@ msgstr ""
msgid "Changing wallet alias only affects the local wallet name."
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Check you connection and try again"
msgstr ""
#: public/views/import.html
msgid "Choose a backup file from your computer"
msgstr ""
@ -176,6 +212,7 @@ msgid "Choose a wallet to send funds"
msgstr ""
#: public/views/includes/topbar.html
#: public/views/modals/advancedSend.html
#: public/views/modals/copayers.html
#: public/views/modals/customized-amount.html
#: public/views/modals/paypro.html
@ -192,14 +229,42 @@ msgstr ""
msgid "Commit hash"
msgstr ""
#: src/js/controllers/copayers.js
#: src/js/controllers/preferencesDelete.js
#: src/js/controllers/walletHome.js
msgid "Confirm"
msgstr ""
#: public/views/modals/tx-details.html
msgid "Confirmations"
msgstr ""
#: src/js/services/bwsError.js
msgid "Copayer already in this wallet"
msgstr ""
#: src/js/services/bwsError.js
msgid "Copayer already registered"
msgstr ""
#: src/js/services/bwsError.js
msgid "Copayer already voted on this spend proposal"
msgstr ""
#: src/js/services/bwsError.js
msgid "Copayer data mismatch"
msgstr ""
#: public/views/modals/copayers.html
msgid "Copayers"
msgstr ""
#: src/js/controllers/backup.js
#: src/js/controllers/copayers.js
#: src/js/controllers/walletHome.js
msgid "Copied to clipboard"
msgstr ""
#: public/views/backup.html
msgid "Copy backup to a safe place"
msgstr ""
@ -213,19 +278,19 @@ msgid "Copy to clipboard"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Could not accept payment. Check you connection and try again"
msgid "Could not accept payment"
msgstr ""
#: src/js/controllers/index.js
msgid "Could not access Wallet Service: Not found"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Could not broadcast payment. Check you connection and try again"
msgid "Could not broadcast payment"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Could not connect wallet service. Check your Internet connexion and your wallet service configuration."
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Could not create address. Check you connection and try again"
#: src/js/services/addressService.js
msgid "Could not create address"
msgstr ""
#: src/js/controllers/walletHome.js
@ -241,7 +306,7 @@ msgid "Could not decrypt file, check your password"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Could not delete payment proposal. Check you connection and try again"
msgid "Could not delete payment proposal"
msgstr ""
#: src/js/controllers/walletHome.js
@ -260,19 +325,23 @@ msgstr ""
msgid "Could not join using the specified extended private key"
msgstr ""
#: src/js/controllers/join.js
msgid "Could not join wallet:"
#: src/js/services/profileService.js
msgid "Could not join wallet"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Could not reject payment. Check you connection and try again"
msgid "Could not recognize a valid Bitcoin QR Code"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Could not reject payment"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Could not send payment"
msgstr ""
#: public/views/walletHome.html
#: src/js/controllers/index.js
msgid "Could not update Wallet"
msgstr ""
@ -309,6 +378,11 @@ msgstr ""
msgid "Creating transaction"
msgstr ""
#: public/views/preferencesFee.html
#: public/views/modals/advancedSend.html
msgid "Current fee rate for this policy: {{fee.feePerKBUnit}}/kiB"
msgstr ""
#: public/views/modals/tx-details.html
msgid "Date"
msgstr ""
@ -340,23 +414,27 @@ msgstr ""
msgid "Details"
msgstr ""
#: src/js/controllers/index.js
msgid "Deutsch"
msgstr ""
#: public/views/preferences.html
msgid "Disabled"
msgstr ""
#: public/views/backup.html
msgid "Do not include private key in backup"
msgstr ""
#: public/views/translators.html
msgid "Don't see your language on Crowdin? Contact the Owner on Crowdin! We'd love to support your language."
msgstr ""
#: public/views/walletHome.html
msgid "Download CSV file"
msgstr ""
#: public/views/backup.html
msgid "Download backup"
msgstr ""
#: public/views/includes/password.html
msgid "ENTER"
msgstr ""
#: src/js/controllers/preferencesFee.js
#: src/js/services/feeService.js
msgid "Economy"
msgstr ""
@ -364,10 +442,6 @@ msgstr ""
msgid "Email Notifications"
msgstr ""
#: src/js/controllers/preferencesFee.js
msgid "Emergency"
msgstr ""
#: public/views/preferences.html
msgid "Encrypt Private Key"
msgstr ""
@ -376,20 +450,16 @@ msgstr ""
msgid "Encrypted backup file saved"
msgstr ""
#: src/js/controllers/index.js
msgid "English"
msgstr ""
#: public/views/includes/password.html
msgid "Enter your password"
msgstr ""
#: src/js/services/profileService.js
msgid "Error creating wallet"
#: src/js/controllers/index.js
msgid "Error at Wallet Service"
msgstr ""
#: src/js/services/profileService.js
msgid "Error creating wallet. Check your internet connection"
msgid "Error creating wallet"
msgstr ""
#: src/js/services/profileService.js
@ -401,6 +471,10 @@ msgstr ""
msgid "Expires"
msgstr ""
#: public/views/backup.html
msgid "Failed to create backup"
msgstr ""
#: src/js/controllers/importLegacy.js
msgid "Failed to import wallets"
msgstr ""
@ -409,19 +483,32 @@ msgstr ""
msgid "Family vacation funds"
msgstr ""
#: public/views/modals/tx-details.html
#: public/views/modals/txp-details.html
msgid "Fee"
msgstr ""
#: public/views/modals/advancedSend.html
msgid "Fee Policy"
msgstr ""
#: public/views/walletHome.html
msgid "Fee policy for this transaction"
msgstr ""
#. Get information of payment if using Payment Protocol
#: src/js/controllers/walletHome.js
msgid "Fetching Payment Information"
msgstr ""
#: src/js/controllers/index.js
#: public/views/translators.html
msgid "French"
msgstr ""
#: src/js/services/bwsError.js
msgid "Funds are locked by pending spend proposals"
msgstr ""
#: src/js/services/notificationsService.js
msgid "Funds received"
msgstr ""
@ -438,6 +525,14 @@ msgstr ""
msgid "Generate new address"
msgstr ""
#: public/views/walletHome.html
msgid "Generating .csv file..."
msgstr ""
#: public/views/translators.html
msgid "German"
msgstr ""
#: public/views/modals/wallets.html
msgid "Getting address for wallet {{selectedWalletName}} ..."
msgstr ""
@ -450,13 +545,19 @@ msgstr ""
msgid "Go back"
msgstr ""
#: public/views/translators.html
msgid "Greek"
msgstr ""
#: public/views/import.html
msgid "Have a Backup from Copay v0.9?"
msgstr ""
#: public/views/backup.html
#: public/views/create.html
#: public/views/join.html
msgid "Hide Advanced options"
#: public/views/walletHome.html
msgid "Hide advanced options"
msgstr ""
#: src/js/controllers/index.js
@ -505,7 +606,35 @@ msgstr ""
msgid "Importing..."
msgstr ""
#: src/js/controllers/index.js
#: src/js/services/bwsError.js
msgid "Incorrect address network"
msgstr ""
#: src/js/services/bwsError.js
msgid "Insufficient funds"
msgstr ""
#: src/js/services/bwsError.js
msgid "Insufficient funds for fee"
msgstr ""
#: public/views/walletHome.html
msgid "Invalid"
msgstr ""
#: src/js/services/bwsError.js
msgid "Invalid address"
msgstr ""
#: src/js/controllers/copayers.js
msgid "Invitation to share a Copay Wallet"
msgstr ""
#: public/views/translators.html
msgid "Italian"
msgstr ""
#: public/views/translators.html
msgid "Japanese"
msgstr ""
@ -518,6 +647,10 @@ msgstr ""
msgid "Join"
msgstr ""
#: src/js/controllers/copayers.js
msgid "Join my Copay wallet. Here is the invitation code: {{secret}} You can download Copay for your phone or desktop at https://copay.io"
msgstr ""
#: public/views/add.html
msgid "Join shared wallet"
msgstr ""
@ -534,6 +667,14 @@ msgstr ""
msgid "Learn more about Wallet Migration"
msgstr ""
#: src/js/services/bwsError.js
msgid "Locktime in effect. Please wait to create a new spend proposal"
msgstr ""
#: src/js/services/bwsError.js
msgid "Locktime in effect. Please wait to remove this spend proposal"
msgstr ""
#: public/views/paymentUri.html
msgid "Make a payment to"
msgstr ""
@ -582,33 +723,46 @@ msgstr ""
msgid "Network"
msgstr ""
#: src/js/services/bwsError.js
msgid "Network connection error"
msgstr ""
#: src/js/services/notificationsService.js
msgid "New Payment Proposal"
msgstr ""
#: public/views/modals/confirmation.html
msgid "No"
#: public/views/walletHome.html
msgid "No Private key"
msgstr ""
#: public/views/walletHome.html
msgid "No transactions yet"
msgstr ""
#: src/js/controllers/preferencesFee.js
#: src/js/services/feeService.js
msgid "Normal"
msgstr ""
#: src/js/services/bwsError.js
msgid "Not authorized"
msgstr ""
#: public/views/walletHome.html
#: public/views/modals/customized-amount.html
msgid "Not valid"
msgstr ""
#: public/views/walletHome.html
#: public/views/includes/output.html
#: public/views/modals/tx-details.html
#: public/views/modals/txp-details.html
msgid "Note"
msgstr ""
#: public/views/includes/alert.html
#: public/views/includes/password.html
msgid "OK"
msgstr ""
#: public/views/modals/tx-status.html
msgid "OKAY"
msgstr ""
@ -712,6 +866,10 @@ msgstr ""
msgid "Payment to"
msgstr ""
#: public/views/walletHome.html
msgid "Pending Confirmation"
msgstr ""
#: public/views/preferencesDeleteWallet.html
msgid "Permanently delete this wallet. THIS ACTION CANNOT BE REVERSED"
msgstr ""
@ -725,11 +883,15 @@ msgstr ""
msgid "Please enter the required fields"
msgstr ""
#: src/js/services/bwsError.js
msgid "Please upgrade Copay to perform this action"
msgstr ""
#: src/js/controllers/import.js
msgid "Please, select your backup file"
msgstr ""
#: src/js/controllers/index.js
#: public/views/translators.html
msgid "Portuguese"
msgstr ""
@ -737,7 +899,11 @@ msgstr ""
msgid "Preferences"
msgstr ""
#: src/js/controllers/preferencesFee.js
#: src/js/controllers/backup.js
msgid "Preparing backup..."
msgstr ""
#: src/js/services/feeService.js
msgid "Priority"
msgstr ""
@ -757,6 +923,11 @@ msgstr ""
msgid "Received"
msgstr ""
#: public/views/includes/output.html
#: public/views/includes/transaction.html
msgid "Recipients"
msgstr ""
#: public/views/walletHome.html
msgid "Reconnecting to Wallet Service..."
msgstr ""
@ -800,6 +971,10 @@ msgstr ""
msgid "Retrying..."
msgstr ""
#: public/views/translators.html
msgid "Russian"
msgstr ""
#: public/views/includes/password.html
msgid "SET"
msgstr ""
@ -913,9 +1088,15 @@ msgstr ""
msgid "Shared Wallet"
msgstr ""
#: public/views/backup.html
#: public/views/create.html
#: public/views/join.html
msgid "Show Advanced options"
#: public/views/walletHome.html
msgid "Show advanced options"
msgstr ""
#: src/js/services/bwsError.js
msgid "Signatures rejected by server"
msgstr ""
#: src/js/controllers/walletHome.js
@ -926,10 +1107,18 @@ msgstr ""
msgid "Signing transaction"
msgstr ""
#: src/js/controllers/index.js
#: public/views/translators.html
msgid "Spanish"
msgstr ""
#: src/js/services/bwsError.js
msgid "Spend proposal is not accepted"
msgstr ""
#: src/js/services/bwsError.js
msgid "Spend proposal not found"
msgstr ""
#: src/js/controllers/copayers.js
#: src/js/controllers/import.js
#: src/js/controllers/preferencesDelete.js
@ -954,7 +1143,7 @@ msgid "The payment was created but could not be completed. Please try again from
msgstr ""
#: src/js/controllers/walletHome.js
msgid "The payment was created but could not be signed. Please try again from home screen."
msgid "The payment was created but could not be signed. Please try again from home screen"
msgstr ""
#: public/views/modals/txp-details.html
@ -962,7 +1151,7 @@ msgid "The payment was removed by creator"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "The payment was signed but could not be broadcasted. Please try again from home screen."
msgid "The payment was signed but could not be broadcasted. Please try again from home screen"
msgstr ""
#: public/views/backup.html
@ -973,6 +1162,10 @@ msgstr ""
msgid "The software you are about to use functions as a free, open source, and multi-signature digital wallet. The software does not constitute an account where BitPay or other third parties serve as financial intermediaries or custodians of your bitcoin. While the software has undergone beta testing and continues to be improved by feedback from the open-source user and developer community, we cannot guarantee that there will be no bugs in the software. You acknowledge that your use of this software is at your own discretion and in compliance with all applicable laws. You are responsible for safekeeping your passwords, private key pairs, PINs and any other codes you use to access the software. IF YOU LOSE ACCESS TO YOUR COPAY WALLET OR YOUR ENCRYPTED PRIVATE KEYS AND YOU HAVE NOT SEPARATELY STORED A BACKUP OF YOUR WALLET AND CORRESPONDING PASSWORD, YOU ACKNOWLEDGE AND AGREE THAT ANY BITCOIN YOU HAVE ASSOCIATED WITH THAT COPAY WALLET WILL BECOME INACCESSIBLE. All transaction requests are irreversible. The authors of the software, employees and affiliates of Bitpay, copyright holders, and BitPay, Inc. cannot retrieve your private keys or passwords if you lose or forget them and cannot guarantee transaction confirmation as they do not have control over the Bitcoin network. To the fullest extent permitted by law, this software is provided “as is” and no representations or warranties can be made of any kind, express or implied, including but not limited to the warranties of merchantability, fitness or a particular purpose and noninfringement. You assume any and all risks associated with the use of the software. In no event shall the authors of the software, employees and affiliates of Bitpay, copyright holders, or BitPay, Inc. be held liable for any claim, damages or other liability, whether in an action of contract, tort, or otherwise, arising from, out of or in connection with the software. We reserve the right to modify this disclaimer from time to time."
msgstr ""
#: src/js/services/bwsError.js
msgid "The spend proposal is not pending"
msgstr ""
#: src/js/controllers/copayers.js
#: src/js/controllers/preferencesDelete.js
msgid "The wallet \"{{walletName}}\" was deleted"
@ -986,6 +1179,10 @@ msgstr ""
msgid "There is an error in the form"
msgstr ""
#: public/views/modals/tx-details.html
msgid "This transaction has become invalid; possibly due to a double spend attempt."
msgstr ""
#: public/views/walletHome.html
msgid "This wallet is not registered at the given Bitcore Wallet Service (BWS). You can recreate it from the local information."
msgstr ""
@ -995,12 +1192,17 @@ msgid "Time"
msgstr ""
#: public/views/walletHome.html
#: public/views/includes/output.html
#: public/views/includes/transaction.html
#: public/views/modals/tx-details.html
#: public/views/modals/txp-details.html
msgid "To"
msgstr ""
#: public/views/includes/output.html
msgid "Total"
msgstr ""
#: public/views/walletHome.html
msgid "Total Locked Balance"
msgstr ""
@ -1009,6 +1211,18 @@ msgstr ""
msgid "Transaction"
msgstr ""
#: src/js/services/bwsError.js
msgid "Transaction already broadcasted"
msgstr ""
#: public/views/translators.html
msgid "Translation Credits"
msgstr ""
#: public/views/preferencesAbout.html
msgid "Translators"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Unable to send transaction proposal"
msgstr ""
@ -1034,6 +1248,11 @@ msgstr ""
msgid "Updating Wallet..."
msgstr ""
#: public/views/preferences.html
#: public/views/walletHome.html
msgid "Use Unconfirmed Funds"
msgstr ""
#: public/views/preferencesAbout.html
msgid "Version"
msgstr ""
@ -1078,6 +1297,7 @@ msgstr ""
msgid "Wallet Invitation is not valid!"
msgstr ""
#: src/js/services/bwsError.js
#: src/js/services/profileService.js
msgid "Wallet already exists"
msgstr ""
@ -1086,18 +1306,34 @@ msgstr ""
msgid "Wallet incomplete and broken"
msgstr ""
#: src/js/services/bwsError.js
msgid "Wallet is full"
msgstr ""
#: src/js/services/bwsError.js
msgid "Wallet is not complete"
msgstr ""
#: public/views/create.html
msgid "Wallet name"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Wallet service timed out. Check your Internet connexion and your wallet service configuration."
#: src/js/services/bwsError.js
msgid "Wallet not found"
msgstr ""
#: src/js/services/bwsError.js
msgid "Wallet service not found"
msgstr ""
#: public/views/preferencesDeleteWallet.html
msgid "Warning!"
msgstr ""
#: public/views/modals/txp-details.html
msgid "Warning: this transaction has unconfirmed inputs"
msgstr ""
#: src/js/services/profileService.js
msgid "Wrong password"
msgstr ""
@ -1158,10 +1394,6 @@ msgstr ""
msgid "too long!"
msgstr ""
#: public/views/preferencesFee.html
msgid "{{fee.value}} bits per kB"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "{{fee}} will be discounted for bitcoin networking fees"
msgstr ""

View File

@ -2,7 +2,7 @@
"name": "copay",
"description": "A multisignature wallet",
"author": "BitPay",
"version": "1.1.1",
"version": "1.1.3",
"keywords": [
"wallet",
"copay",
@ -12,6 +12,8 @@
],
"main": "public/index.html",
"window": {
"title": "Copay - A multisignature wallet",
"icon": "./public/img/icons/icon-256.png",
"toolbar": false,
"show": true,
"visible": true,
@ -45,11 +47,10 @@
"grunt-cli": "^0.1.13",
"grunt-contrib-concat": "^0.5.1",
"grunt-contrib-copy": "^0.8.0",
"grunt-contrib-compress": "^0.13.0",
"grunt-contrib-uglify": "^0.8.0",
"grunt-contrib-watch": "^0.5.3",
"grunt-exec": "^0.4.6",
"grunt-markdown": "^0.5.0",
"grunt-release": "^0.7.0",
"shelljs": "^0.3.0"
},
"scripts": {
@ -57,10 +58,10 @@
"test": "./node_modules/.bin/grunt test-coveralls"
},
"devDependencies": {
"adm-zip": "^0.4.7",
"angular": "^1.3.14",
"angular-mocks": "^1.3.14",
"grunt-contrib-compress": "^0.13.0",
"grunt-contrib-copy": "^0.8.0",
"bhttp": "^1.2.1",
"grunt-karma": "^0.10.1",
"grunt-karma-coveralls": "^2.5.3",
"grunt-node-webkit-builder": "^1.0.2",

2149
po/es.po

File diff suppressed because it is too large Load Diff

1103
po/pt.po

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -24,8 +24,8 @@
<div ng-include="'views/includes/sidebar.html'" ng-if="index.hasProfile"></div>
<div notifications="right top"></div>
<div ng-include="'views/includes/password.html'" ng-if="index.askPassword"
></div>
<div ng-include="'views/includes/password.html'" ng-if="index.askPassword"></div>
<div ng-include="'views/includes/alert.html'" ng-if="index.showAlert"></div>
<div id="sectionContainer">
<div id="mainSection">
<section ui-view="main"

View File

@ -7,9 +7,14 @@
<div class="content p20v" ng-controller="backupController as backup">
<div class="row m20t">
<div class="columns" ng-show="!backup.backupWalletPlainText && !backup.error">
<div class="text-warning size-14 m10v" ng-show="backup.isEncrypted">
<div class="row">
<div class="columns" ng-show="!backup.backupWalletPlainText">
<div class="text-warning size-14 m20b" ng-show="backup.error">
<i class="fi-alert size-12"></i>
<span translate> Failed to create backup </span>
</div>
<div class="text-warning size-14 m20b" ng-show="backup.isEncrypted">
<i class="fi-alert size-12"></i>
<span translate> The private key for this wallet is encrypted. Exporting a backup will keep the private key encrypted in the backup archive.</span>
@ -29,30 +34,56 @@
name="password" ng-model="backup.repeatpassword">
</div>
<button class="black round expand" ng-click="backup.downloadWalletBackup()"
<div class="m10t oh" ng-init="hideAdv=true">
<a class="button outline light-gray expand tiny" ng-click="hideAdv=!hideAdv">
<i class="fi-widget m3r"></i>
<span translate ng-hide="!hideAdv">Show advanced options</span>
<span translate ng-hide="hideAdv">Hide advanced options</span>
<i ng-if="hideAdv" class="icon-arrow-down4"></i>
<i ng-if="!hideAdv" class="icon-arrow-up4"></i>
</a>
</div>
<div ng-hide="hideAdv" class="row">
<div class="large-12 columns">
<label for="no-sign" class="line-b oh">
<span translate>Do not include private key in backup</span>
<switch id="no-sign" name="noSign" ng-model="noSign" class="green right m5t m10b"></switch>
</label>
</div>
<div class="m10 size-14 text-gray" translate>
A backup without its private key will allow the user to see the wallet balance, transactions, and create spend proposals. However, it will not be able to approve (sign) proposals.
</div>
</div>
<button class="black round expand m0" ng-click="backup.downloadWalletBackup()"
ng-disabled="(!backup.password || backup.password != backup.repeatpassword)"
ng-style="{'background-color':index.backgroundColor}"
ng-show="!backup.isSafari && !backup.isCordova"><i class="fi-download"></i>
<span translate>Download backup</span></button>
<button class="black round expand" ng-click="backup.viewWalletBackup()"
<button class="black round expand m0" ng-click="backup.viewWalletBackup()"
ng-disabled="(!backup.password || backup.password != backup.repeatpassword)"
ng-style="{'background-color':index.backgroundColor}"
ng-show="backup.isSafari && !backup.isCordova"><i class="fi-eye"></i>
<span translate>View backup</span></button>
<div ng-show="backup.isCordova">
<h4 translate>Backup options</h4>
<button class="black round expand" ng-disabled="(!backup.password || backup.password != backup.repeatpassword)"
<button class="black round expand" ng-disabled="(!backup.password || backup.password != backup.repeatpassword)"
ng-style="{'background-color':index.backgroundColor}"
ng-click="backup.copyWalletBackup()"><i class="fi-clipboard-pencil"></i>
<span translate>Copy to clipboard</span></button>
<button class="black round expand" ng-disabled="(!backup.password || backup.password != backup.repeatpassword)"
<button class="black round expand m0" ng-disabled="(!backup.password || backup.password != backup.repeatpassword)"
ng-style="{'background-color':index.backgroundColor}"
ng-click="backup.sendWalletBackup()"><i class="fi-mail"></i>
<span translate>Send by email</span></button>
</div>
</div>
</div>
<div class="row m20b" ng-show="backup.backupWalletPlainText">
<div class="row" ng-show="backup.backupWalletPlainText">
<div class="large-12 columns">
<h3 translate>Copy backup to a safe place</h3>
<div class="input">
@ -65,8 +96,11 @@
</div>
</div>
<div class="m10 size-14 text-gray" translate>
* You can safely install your backup on another device and use your wallet from multiple devices at the same time.
<div class="row m10t">
<div class="columns size-14 text-gray" translate>
* You can safely install your backup on another device and use your wallet from multiple devices at the same time.
</div>
</div>
</div>
<div class="extra-margin-bottom"></div>

View File

@ -81,8 +81,8 @@
<div class="m10t oh" ng-init="hideAdv=true">
<a class="button outline light-gray expand tiny" ng-click="hideAdv=!hideAdv">
<i class="fi-widget m3r"></i>
<span translate ng-hide="!hideAdv">Show Advanced options</span>
<span translate ng-hide="hideAdv">Hide Advanced options</span>
<span translate ng-hide="!hideAdv">Show advanced options</span>
<span translate ng-hide="hideAdv">Hide advanced options</span>
<i ng-if="hideAdv" class="icon-arrow-down4"></i>
<i ng-if="!hideAdv" class="icon-arrow-up4"></i>
</a>

View File

@ -10,7 +10,7 @@
<div class="content p20b" ng-class="{'disclaimer':!index.hasProfile}">
<h4 class="title m0" ng-show="!index.hasProfile">
<span translate>Terms of Use</span>
<img class="right" src="img/logo.svg" alt="Copay" width="40">
<logo class="right" width="40"></logo>
</h4>
<div class="p20h m10t">
<p class="enable_text_select text-light size-14 text-gray" translate>
@ -19,11 +19,13 @@
<div ng-show="!agreed">
<p translate>I affirm that I have read, understood, and agree with these terms.</p>
<button class="black round expand" ng-click="agree()">
<span translate> Agree </span>
<button class="black round expand" ng-click="agree()" ng-disabled="loading" translate>
Agree
</button>
</div>
<button ng-show="agreed && !index.hasProfile" class="round" ng-click="agree()" translate>Go back</button>
<button ng-show="agreed && !index.hasProfile" class="round expand" ng-click="agree()" translate>
Go back
</button>
</div>
<div class="extra-margin-bottom"></div>
</div>

View File

@ -0,0 +1,14 @@
<div class="passModalMask">
</div>
<div class="alertModal">
<div class="columns m20t">
<div class="m20t size-14 text-center">
<i class="fi-alert"></i>
{{index.showAlert.msg|translate}}
</div>
<div class="text-center m20t" ng-click="index.showAlert.close()">
<a class="button outline light-gray round tiny small-4" translate>OK</a>
</div>
</div>
</div>

View File

@ -0,0 +1,5 @@
<div class="medium-2 small-2 columns text-center bottombar-item">
<a ng-click="showPlugins ? showPlugins = false : showPlugins = true" class="menu-toggle">
<i class="size-24 db" ng-class="{ 'icon-arrow-left': showPlugins, 'icon-arrow-right' : !showPlugins }"> </i>
</a>
</div>

View File

@ -1,5 +1,21 @@
<div class="bottom-bar row collapse">
<div class="medium-3 small-3 columns text-center bottombar-item" ng-repeat="item in index.menu">
<div class="bottom-bar second-bottom-bar row collapse animated slideInRight" ng-class="{ 'slideOutRight': !showPlugins }" ng-show="index.menu.length > 6">
<div class="medium-{{index.menuItemSize}} small-{{index.menuItemSize}} columns text-center bottombar-item" ng-repeat="item in index.menu | limitTo: 5 - index.menu.length">
<a ng-click="index.setTab(item.link)" ng-class="{'active': index.tab == item.link}" id="menu-{{item.link}}">
<i class="size-24 {{item.icon}} db"></i>
<div class="size-10 tu">
{{item.title|translate}}
</div>
</a>
</div>
<div class="medium-{{index.menuItemSize}} small-{{index.menuItemSize}} columns text-center bottombar-item" ng-repeat="n in index.menu | limitTo: 4 - index.menu.length % 6">
<a></a>
</div>
<menu-toggle ng-show="index.menu.length > 6"/>
</div>
<div class="bottom-bar row collapse">
<div class="medium-{{index.menuItemSize}} small-{{index.menuItemSize}} columns text-center bottombar-item" ng-repeat="item in index.menu | limitTo: (index.menu.length > 6 ? 5 : 6)">
<a ng-click="index.setTab(item.link)" ng-class="{'active': index.tab == item.link}" id="menu-{{item.link}}">
<i class="size-24 {{item.icon}} db"></i>
<div class="size-10 tu">
@ -10,4 +26,12 @@
</div>
</a>
</div>
<div class="medium-2 small-2 columns text-center bottombar-item" ng-show="index.menu.length == 5">
<a></a>
</div>
<menu-toggle ng-show="index.menu.length > 6"/>
</div>

View File

@ -0,0 +1,14 @@
<li class="p10 oh" ng-click="copyAddress(output.toAddress)">
<span class="text-gray" translate>To</span>:
<span class="right enable_text_select">{{output.toAddress || output.address}}</span>
</li>
<li class="p10">
<span class="text-gray" translate>Amount</span>:
<span class="right">{{output.amountStr}}
<span ng-show="output.alternativeAmountStr" class="label gray radius">{{output.alternativeAmountStr}}</span>
</span>
</li>
<li class="p10 oh">
<span class="text-gray" translate>Note</span>:
<span class="right">{{output.message}}</span>
</li>

View File

@ -30,7 +30,7 @@
<button class="round expand" ng-click="pass.set(index.askPassword.isSetup, index.askPassword.callback)" ng-disabled="!pass.password"
ng-style="{'background-color':index.backgroundColor}">
<span translate ng-if="index.askPassword.isSetup" translate>SET</span>
<span translate ng-if="!index.askPassword.isSetup" translate>ENTER</span>
<span translate ng-if="!index.askPassword.isSetup" translate>OK</span>
</button>
</div>
</div>

View File

@ -1,6 +1,6 @@
<nav class="sidebar left-off-canvas-menu" ng-controller="sidebarController as sidebar">
<header>
<img src="img/logo-negative.svg" alt="Copay" width="80">
<logo negative="true" width="80"></logo>
<div ng-include="'views/includes/version.html'"></div>
</header>
<ul class="off-canvas-list">

View File

@ -15,8 +15,7 @@
</section>
<section class="right-small" ng-show="showCamera">
<a id="camera-icon" ng-show="index.isComplete" class="p10"
ng-click="topbar.openScanner()"><i class="icon-scan size-21"></i></a>
<qr-scanner ng-show="index.isComplete" on-scan="topbar.onQrCodeScanned(data)" before-scan="topbar.openSendScreen()" />
</section>
<section class="middle tab-bar-section">

View File

@ -11,13 +11,20 @@
<time class="right size-12 text-gray m5t">{{ (tx.ts || tx.createdOn ) * 1000 | amTimeAgo}}</time>
</div>
<div class="ellipsis size-14">
<span translate>To</span>:
<span ng-if="tx.merchant">
<span ng-show="tx.merchant.pr.ca"><i class="fi-lock"></i> {{tx.merchant.domain}}</span>
<span ng-show="!tx.merchant.pr.ca"><i class="fi-unlock"></i> {{tx.merchant.domain}}</span>
<span ng-if="tx.hasMultiplesOutputs">
<span translate>Recipients</span>:
<span>{{tx.recipientCount}}</span>
</span>
<span ng-if="!tx.hasMultiplesOutputs">
<span translate>To</span>:
<span ng-if="tx.merchant">
<span ng-show="tx.merchant.pr.ca"><i class="fi-lock"></i> {{tx.merchant.domain}}</span>
<span ng-show="!tx.merchant.pr.ca"><i class="fi-unlock"></i> {{tx.merchant.domain}}</span>
</span>
<span ng-if="!tx.merchant">
{{tx.toAddress}}
</span>
</span>
<contact address="{{tx.toAddress}}" ng-hide="tx.merchant"> </contact>
{{tx.toAddress}}
</div>
<div class="ellipsis text-gray size-14">
{{tx.message}}

View File

@ -66,8 +66,8 @@
<a class="button outline light-gray tiny expand" ng-click="join.hideAdv=!join.hideAdv">
<i class="fi-widget m3r"></i>
<span translate ng-show="!join.hideAdv">Show Advanced options</span>
<span translate ng-show="join.hideAdv">Hide Advanced options</span>
<span translate ng-show="!join.hideAdv">Show advanced options</span>
<span translate ng-show="join.hideAdv">Hide advanced options</span>
<i ng-show="!join.hideAdv" class="icon-arrow-down4"></i>
<i ng-show="join.hideAdv" class="icon-arrow-up4"></i>
</a>

View File

@ -0,0 +1,34 @@
<nav class="tab-bar">
<section class="left-small">
<a ng-click="cancel()" class="p10">
<span class="text-close" translate>Close</span>
</a>
</section>
<section class="middle tab-bar-section">
<h1 class="title ellipsis" ng-style="{'color':color}" translate>
Advanced Send
</h1>
</section>
</nav>
<div class="modal-content fix-modals-touch">
<ul class="no-bullet m0 size-14">
<h4 class="title m0" translate>Fee Policy</h4>
<li ng-repeat="fee in (network == 'livenet' ? feeLevels.livenet : feeLevels.testnet)" ng-click="save(fee.level)" class="line-b p20">
<span class="text-capitalize">{{fee.level|translate}}</span>
<i class="fi-check size-16 right" ng-show="currentFeeLevel == fee.level"></i>
</li>
</ul>
<div class="row column m20t">
<div class="text-gray size-12 text-center" ng-repeat="fee in (network == 'livenet' ? feeLevels.livenet :
feeLevels.testnet)" ng-if="fee.level == currentFeeLevel">
<span translate>Average confirmation time: {{fee.nbBlocks * 10}} minutes</span>.
<span class="size-12 text-light" translate>Current fee rate for this policy: {{fee.feePerKBUnit}}/kiB</span>
</div>
</div>
<div class="extra-margin-bottom"></div>
</div>

View File

@ -1,16 +1,16 @@
<div class="m20tp text-center">
<div class="row">
<h1 class="text-center m20b">{{title|translate}}</h1>
<div class="large-6 medium-6 small-6 columns">
<button class="button light-gray expand outline round" ng-disabled="loading"
ng-click="cancel()">
<i class="fi-x"></i> <span class="tu" translate>No</span>
</button>
</div>
<div class="large-6 medium-6 small-6 columns">
<button class="button warning expand round" ng-disabled="loading" ng-click="ok()">
<i class="fi-trash"></i> <span translate>Yes</span>
</button>
</div>
<div class="large-6 medium-6 small-6 columns">
<button class="button light-gray expand outline round" ng-disabled="loading"
ng-click="cancel()">
<i class="fi-x"></i> <span class="tu" translate>Cancel</span>
</button>
</div>
</div>
</div>

View File

@ -53,7 +53,7 @@
<span translate>Amount</span>
</label>
<div class="input">
<input type="number" id="amount" name="amount" ng-attr-placeholder="{{'Amount'|translate}}"
<input type="number" id="amount" name="amount" ng-attr-placeholder="{{'Amount'|translate}}"
ng-model="_customAmount" valid-amount required autocomplete="off">
<input type="number" id="alternative" name="alternative" ng-model="_customAlternative" style="display:none">
<a class="postfix" ng-click="toggleAlternative()">{{unitName}}</a>
@ -63,8 +63,8 @@
<label for="alternative"><span translate>Amount in</span> {{ alternativeName }}
</label>
<div class="input">
<input type="number" id="alternative" name="alternative" ng-attr-placeholder="{{'Amount'|translate}}"
ng-model="_customAlternative" requiredautocomplete="off" required>
<input type="number" id="alternative" name="alternative" ng-attr-placeholder="{{'Amount'|translate}}"
ng-model="_customAlternative" required autocomplete="off" required>
<input type="number" id="amount" name="amount" ng-model="_customAmount" style="display:none">
<a class="postfix" ng-click="toggleAlternative()"> {{ alternativeIsoCode }}</a>
</div>

View File

@ -14,17 +14,19 @@
<div class="modal-content fix-modals-touch">
<div class="header-modal text-center">
<div class="size-42">
<span ng-if="btx.action == 'received'">+</span><span ng-if="btx.action == 'sent'">-</span>{{btx.amountStr}} {{settings.unitName}}
<div class="size-42" ng-show="btx.action != 'invalid'">
<span ng-if="btx.action == 'received'">+</span><span ng-if="btx.action == 'sent'">-</span>{{btx.amountStr}}
</div>
<div class="size-18 m5t text-gray" ng-show="btx.alternativeAmount">
{{btx.alternativeAmount}} {{settings.alternativeIsoCode}}
<div class="size-42" ng-show="btx.action == 'invalid'">
-
</div>
</div>
<h4 class="title m0" translate>Details</h4>
<ul class="no-bullet size-14 m0">
<li ng-if="btx.addressTo && btx.addressTo != 'N/A'" class="line-b p10 oh" ng-click="copyAddress(btx.addressTo)">
<ul class="no-bullet size-14 m0">
<li ng-if="!btx.hasMultiplesOutputs && btx.addressTo && btx.addressTo != 'N/A'" class="line-b p10 oh" ng-click="copyAddress(btx.addressTo)">
<span class="text-gray" translate>To</span>:
<span class="right">
<span ng-if="btx.merchant">
@ -32,21 +34,47 @@
<span ng-show="!btx.merchant.pr.ca"><i class="fi-unlock color-yellowi"></i> {{btx.merchant.domain}}</span>
</span>
<span ng-if="!btx.merchant">
<span class="text-gray enable_text_select"> {{btx.labelTo || btx.addressTo}}</span>
<span class="enable_text_select"> {{btx.labelTo || btx.addressTo}}</span>
</span>
</span>
</li>
<li ng-show="btx.hasMultiplesOutputs" class="line-b p10 oh"
ng-click="showMultiplesOutputs = !showMultiplesOutputs">
<span class="text-gray" translate>Recipients</span>:
<span class="right">{{btx.recipientCount}}
<i ng-show="showMultiplesOutputs" class="icon-arrow-up3 size-24"></i>
<i ng-show="!showMultiplesOutputs" class="icon-arrow-down3 size-24"></i>
</span>
</li>
<div class="line-b" ng-show="btx.hasMultiplesOutputs && showMultiplesOutputs"
ng-repeat="output in btx.outputs"
ng-include="'views/includes/output.html'">
</div>
<li ng-show="btc.message" class="line-b p10 oh">
<span class="text-gray" translate>Note</span>:
<span class="right">{{btx.message}}</span>
</li>
<li ng-if="btx.action == 'invalid'" class="line-b p10 oh">
<span class="right" translate>
This transaction has become invalid; possibly due to a double spend attempt.
</span>
<li ng-if="btx.time" class="line-b p10 oh">
<span class="text-gray" translate>Date</span>:
<span class="right">
<time>{{ btx.time * 1000 | amCalendar}}</time>
</span>
</li>
<li ng-if="btx.message" class="line-b p10 oh">
<span class="text-gray" translate>Note</span>:
<span class="right">
{{btx.message}}
</span>
<li class="line-b p10" ng-show="btx.action != 'received'">
<span class="text-gray" translate>Fee</span>:
<span class="right">{{btx.feeStr}}</span>
</li>
<li class="line-b p10 oh" ng-if="btx.message && btx.action != 'received'">
<span class="text-gray" translate>Note</span>:
<span class="right">{{btx.message}}</span>
</li>
<li ng-if="btx.merchant" class="line-b p10 oh">
<span class="text-gray" translate>Merchant message</span>:

View File

@ -14,20 +14,42 @@
<div class="modal-content fix-modals-touch" ng-init="updateCopayerList()">
<h4 class="title m0" translate>Details</h4>
<ul class="no-bullet size-14 m0">
<li class="line-b p10 oh" ng-click="copyAddress(tx.toAddress)">
<li ng-if="!tx.hasMultiplesOutputs"
class="line-b p10 oh"
ng-click="copyAddress(tx.toAddress)">
<span class="text-gray" translate>To</span>:
<span class="right enable_text_select">{{tx.toAddress}}</span>
</li>
<li class="line-b p10">
<span class="text-gray" translate>Amount</span>:
<span class="right">{{amountStr}}
<span class="label gray radius">{{alternativeAmountStr}}</span>
<span ng-show="tx.hasMultiplesOutputs" class="text-gray" translate>Total</span>
<span ng-show="!tx.hasMultiplesOutputs" class="text-gray" translate>Amount</span>:
<span class="right">{{tx.amountStr}}
<span ng-show="tx.alternativeAmountStr" class="label gray radius">{{tx.alternativeAmountStr}}</span>
</span>
</li>
<li class="line-b p10 oh">
<span class="text-gray" translate>Note</span>:
<span class="right">{{tx.message}}</span>
</li>
<li ng-show="tx.hasMultiplesOutputs" class="line-b p10 oh"
ng-click="showMultiplesOutputs = !showMultiplesOutputs">
<span class="text-gray" translate>Recipients</span>:
<span class="right">{{tx.recipientCount}}
<i ng-show="showMultiplesOutputs" class="icon-arrow-up3 size-24"></i>
<i ng-show="!showMultiplesOutputs" class="icon-arrow-down3 size-24"></i>
</span>
</li>
<div class="line-b" ng-show="tx.hasMultiplesOutputs && showMultiplesOutputs"
ng-repeat="output in tx.outputs"
ng-include="'views/includes/output.html'">
</div>
<li class="line-b p10">
<span class="text-gray" translate>Fee</span>:
<span class="right">{{feeStr}}</span>
</li>
<span class="right">{{tx.feeStr}}</span>
</li>
<li class="line-b p10">
<span class="text-gray" translate>Time</span>:
<span class="right">
@ -38,11 +60,10 @@
<span class="text-gray" translate>Created by</span>:
<span class="right">{{tx.creatorName}}</span>
</li>
<li class="line-b p10 oh">
<span class="text-gray" translate>Note</span>:
<span class="right">{{tx.message}}</span>
</li>
</ul>
<div class="p10 text-center size-12" ng-show="!currentSpendUnconfirmed && tx.hasUnconfirmedInputs">
<span class="text-warning" translate>Warning: this transaction has unconfirmed inputs</span>
</div>
<div ng-if="tx.paypro">
<h4 class="title m0" translate>Payment details</h4>
<ul class="no-bullet size-14 m0">
@ -102,7 +123,7 @@
<span translate>Reject</span>
</button>
</div>
<div class="large-5 medium-5 small-6 columns text-right">
<div class="large-5 medium-5 small-6 columns text-right" ng-show="canSign">
<button class="button primary round expand" ng-click="sign(tx)"
ng-style="{'background-color':color}"
ng-disabled="loading">
@ -112,7 +133,7 @@
</div>
</div>
<div class="text-center text-gray" ng-show="tx.status != 'pending'">
<div class="text-center text-gray m20b" ng-show="tx.status != 'pending'">
<div class="m10t"
ng-show="tx.status=='accepted'" translate>
Payment accepted...
@ -130,7 +151,7 @@
ng-show="tx.status=='broadcasted'" translate>
Payment sent!
</div>
<div class="text-center text-warning"
<div class="text-center text-warning m10t"
ng-show="tx.status=='rejected'" translate>
Payment finally rejected
</div>

View File

@ -8,7 +8,7 @@
<div class="content preferences" ng-controller="preferencesController as preferences">
<ul class="no-bullet m0 size-14" ng-show="!index.noFocusedWallet">
<ul class="no-bullet m0 size-14" ng-show="!index.noFocusedWallet">
<h4 class="title m0">{{index.alias}} [{{index.walletName}}] <span translate>settings</span></h4>
@ -55,37 +55,39 @@
<h4 class="title m0" translate>Global settings</h4>
<li class="line-b p20" ng-click="$root.go('preferencesLanguage')">
<li class="line-b p20" ng-show="!index.noFocusedWallet" ng-click="$root.go('preferencesLanguage')">
<span translate>Language</span>
<span class="right text-gray">
<i class="icon-arrow-right3 size-24 right"></i>
{{index.defaultLanguageName|translate}}
</span>
</li>
<li class="line-b p20" ng-click="$root.go('preferencesUnit')">
<li class="line-b p20" ng-show="!index.noFocusedWallet" ng-click="$root.go('preferencesUnit')">
<span translate>Unit</span>
<span class="right text-gray">
<i class="icon-arrow-right3 size-24 right"></i>
{{preferences.unitName}}
</span>
</li>
<li class="line-b p20" ng-click="$root.go('preferencesAltCurrency')">
<li class="line-b p20" ng-show="!index.noFocusedWallet" ng-click="$root.go('preferencesAltCurrency')">
<span translate>Alternative Currency</span>
<span class="right text-gray">
<i class="icon-arrow-right3 size-24 right"></i>
{{preferences.selectedAlternative.name}}
</span>
</li>
<li class="line-b p20" ng-click="$root.go('preferencesFee')">
<li class="line-b p20" ng-show="!index.noFocusedWallet" ng-click="$root.go('preferencesFee')"
ng-show="(index.network == 'livenet' ? index.feeLevels.livenet : index.feeLevels.testnet)">
<span translate>Bitcoin Network Fee Policy</span>
<span class="right text-gray">
<i class="icon-arrow-right3 size-24 right"></i>
{{preferences.feeName|translate}}
{{index.feeOpts[index.currentFeeLevel]|translate}}
</span>
</li>
<li class="line-b p20" ng-show="!index.noFocusedWallet">
<span translate>Use Unconfirmed Funds</span>
<switch id="spend-unconfirmed" name="spendUnconfirmed" ng-model="spendUnconfirmed" class="green right"></switch>
</li>
<li class="line-b p20" ng-click="$root.go('preferencesBwsUrl')">
<span>Bitcore Wallet Service</span>
<span class="text-gray db">

View File

@ -6,7 +6,7 @@
<div class="content preferences p20v" ng-controller="preferencesAbout as about">
<div class="text-center small-5 small-centered columns m20b" >
<img src="img/logo.png" alt="Copay" width="100%">
<logo></logo>
</div>
<h4 class="title m0" translate>Release Information</h4>
@ -33,6 +33,10 @@
<i class="icon-arrow-right3 size-24 right text-gray"></i>
<span translate>Terms of Use</span>
</li>
<li class="line-b p20" ng-click="$root.go('translators')">
<i class="icon-arrow-right3 size-24 right text-gray"></i>
<span translate>Translators</span>
</li>
<li class="line-b p20" ng-conf ng-click="$root.go('logs')">
<i class="icon-arrow-right3 size-24 right text-gray"></i>
<span translate>Session log</span>

View File

@ -3,20 +3,30 @@
ng-include="'views/includes/topbar.html'"
ng-init="titleSection='Bitcoin Network Fee Policy'; goBackToState = 'preferences'; noColor = true">
</div>
<div class="content preferences" ng-controller="preferencesFeeController as prefFee">
<div ng-repeat="fee in prefFee.feeOpts" ng-click="prefFee.save(fee)" class="line-b p20 size-14">
<span ng-if="fee.red" style="color:red">{{fee.name|translate}} (<span translate>{{fee.value}} bits per kB</span>)</span>
<span ng-if="!fee.red">{{fee.name|translate}} (<span translate>{{fee.value}} bits per kB</span>)</span>
<i class="fi-check size-16 right" ng-show="prefFee.feeName == fee.name"></i>
</div>
<div class="row column m20t">
<div class="text-gray size-12 text-center m20b" translate>
Bitcoin transactions may include a fee collected by miners on the network. The higher the fee, the greater the incentive a miner has to include that transaction in a block. The Emergency level should only be used when there is a network congestion.
<ul class="no-bullet m0 size-14">
<li ng-repeat="fee in (index.network == 'livenet' ? index.feeLevels.livenet : index.feeLevels.testnet)"
ng-click="prefFee.save(fee.level)" class="line-b p20">
{{index.feeOpts[fee.level]|translate}}
<i class="fi-check size-16 right" ng-show="index.currentFeeLevel == fee.level"></i>
</li>
</ul>
<div class="row m20t">
<div class="text-gray size-12 text-center" ng-repeat="fee in (index.network == 'livenet' ? index.feeLevels.livenet :
index.feeLevels.testnet)" ng-if="fee.level == index.currentFeeLevel">
<div ng-show="fee.nbBlocks">
<span translate>Average confirmation time: {{fee.nbBlocks * 10}} minutes</span>.
</div>
<span class="size-12 text-light" translate>Current fee rate for this policy: {{fee.feePerKBUnit}}/kiB</span>
</div>
</div>
<div class="row m20t">
<div class="text-gray size-12 text-center" translate>
Bitcoin transactions may include a fee collected by miners on the network. The higher the fee, the greater the incentive a miner has to include that transaction in a block. Actual fees are determined based on network load and the selected policy.
</div>
</div>
</div>
<div class="extra-margin-bottom"></div>

View File

@ -11,7 +11,7 @@
<div ng-show="!prefLang.loading"
ng-repeat="lang in index.availableLanguages"
ng-click="prefLang.save(lang.isoCode)" class="line-b p20 size-14">
<span>{{lang.name|translate}}</span>
<span>{{lang.name}}</span>
<i class="fi-check size-16 right" ng-show="index.defaultLanguageIsoCode == lang.isoCode"></i>
</div>
</div>

View File

@ -8,8 +8,8 @@
<div class="content p20v" ng-controller="preferencesLogs as logs">
<div class="row columns">
<button class="black radius small expand" ng-show="logs.isCordova" ng-style="{'background-color':index.backgroundColor}" ng-click="logs.sendLogs()" ><i class="fi-mail"></i>
<div class="row columns large-centered medium-centered">
<button class="black round small expand" ng-show="logs.isCordova" ng-style="{'background-color':index.backgroundColor}" ng-click="logs.sendLogs()"><i class="fi-mail"></i>
<span translate>Send by email</span>
</button>

View File

@ -1,14 +1,16 @@
<div class="text-center splash" ng-if="!index.hasProfile">
<div class="splash content text-center" ng-if="!index.hasProfile">
<div class="row">
<div class="medium-6 large-4 medium-centered small-centered large-centered columns">
<div class="p20">
<div class="medium-centered small-centered large-centered columns">
<div class="m20t">
<span class="text-bold size-16 text-white" translate>WELCOME TO COPAY</span>
<p class="text-gray size-14 m0 text-light" translate>A multisignature bitcoin wallet</p>
</div>
</div>
</div>
<div class="gif-splash">
<img src="img/icon-splash.png" alt="icon" width="25%">
<div class="row">
<div class="container-image large-3 medium-3 small-3 medium-centered small-centered large-centered columns">
<img src="img/icon-splash.png" alt="icon" width="100%">
</div>
</div>
<div class="text-center size-12 text-warning" ng-show="error && !creatingProfile">
{{(error)|translate}}. <span translate>Retrying...</span>
@ -25,9 +27,13 @@
<span translate>Creating Profile...</span>
</div>
</div>
<div class="row columns start-button" ng-show="!creatingProfile">
<button ng-click="create()" class="button black expand round size-12 text-spacing" translate> GET STARTED </button>
<p class="text-gray m5b size-12" translate>Already have a wallet?</p>
<button ng-click="create(true)" class="button round outline dark-gray tiny" translate>Import backup </button>
<div class="row" ng-show="!creatingProfile">
<div class="start-button large-8 medium-8 small-8 medium-centered small-centered large-centered columns">
<button ng-click="create()" class="button black expand round size-12 text-spacing" translate>
GET STARTED
</button>
<p class="text-gray m5b size-12" translate>Already have a wallet?</p>
<button ng-click="create(true)" class="button round outline dark-gray tiny" translate>Import backup </button>
</div>
</div>
</div>

View File

@ -0,0 +1,38 @@
<div
class="topbar-container"
ng-include="'views/includes/topbar.html'"
ng-init="titleSection='Translators'; goBackToState = 'about'">
</div>
<div class="content p20v">
<div class="text-center m20b">
<img src="img/copay_crowdin.png" alt="Copay and Crowdin" width="340" height="70">
</div>
<h4 class="title m0" translate>Translation Credits</h4>
<ul class="no-bullet m0 size-14">
<li class="line-b p10">kinoshitajona<span class="right text-gray size-12" translate>Japanese</span></li>
<li class="line-b p10">Kirvx<span class="right text-gray size-12" translate>French</span></li>
<li class="line-b p10">HostFat<span class="right text-gray size-12" translate>Italian</span></li>
<li class="line-b p10">koalalorenzo<span class="right text-gray size-12" translate>Italian</span></li>
<li class="line-b p10">nicolazza<span class="right text-gray size-12" translate>Italian</span></li>
<li class="line-b p10">saschad<span class="right text-gray size-12" translate>German</span></li>
<li class="line-b p10">8597fde7<span class="right text-gray size-12" translate>German</span></li>
<li class="line-b p10">pmichelazzo<span class="right text-gray size-12" translate>Portuguese</span></li>
<li class="line-b p10">johnblazakis<span class="right text-gray size-12" translate>Greek</span></li>
<li class="line-b p10">chek2fire1<span class="right text-gray size-12" translate>Greek</span></li>
<li class="line-b p10">cmgustavo83<span class="right text-gray size-12" translate>Spanish</span></li>
<li class="line-b p10">lax5<span class="right text-gray size-12" translate>Russian</span></li>
</ul>
<div class="row m20t">
<div class="size-12 text-gray text-center">
<p class="size-12 text-black">
<span translate>All contributions to Copay's translation are welcome. Sign up at crowdin.com and join the Copay project at</span>
<a href ng-click="$root.openExternalLink('https://crowdin.com/project/copay')">https://crowdin.com/project/copay</a>.
</p>
<span translate>
Don't see your language on Crowdin? Contact the Owner on Crowdin! We'd love to support your language.
</span>
</div>
</div>
</div>
<div class="extra-margin-bottom"></div>

View File

@ -1,6 +1,6 @@
<div class="row columns p20">
<div class="text-center">
<img src="img/logo.svg" alt="Copay" width="146" height="59">
<logo width="146"></logo>
<div class="text-white" ng-include="'views/includes/version.html'"></div>
</div>
<h1 translate class="text-center">Browser unsupported</h1>

View File

@ -76,7 +76,7 @@
<div class="amount" ng-style="{'background-color':index.backgroundColor}">
<div ng-if="!index.anyOnGoingProcess && !index.notAuthorized">
<div ng-show="index.updateError" ng-click='index.openWallet(); index.updateTxHistory()'>
<span class="size-12 db m10b" translate>Could not update Wallet</span>
<span class="size-12 db m10b">{{index.updateError|translate}}</span>
<button class="outline white tiny round" translate>Tap to retry</button>
</div>
@ -91,6 +91,12 @@
ng-if="index.totalBalanceAlternative">
{{index.totalBalanceAlternative}} {{index.alternativeIsoCode}}
</div>
<div class="size-14"
ng-if="index.pendingAmount">
<span translate>Pending Confirmation</span>:
{{index.pendingAmountStr}}
</div>
</div>
</div>
@ -119,6 +125,7 @@
<div class="size-12 text-gray">
<span translate>Multisignature wallet</span> ({{index.m}} <span translate>of</span> {{index.n}})
<span ng-if="index.network != 'livenet'">- Testnet</span>
<span ng-if="!index.canSign"> - <span translate>No Private key</span></span>
</div>
</div>
<div ng-show="!index.isShared">
@ -127,6 +134,7 @@
</p>
<div class="size-12 text-gray" ng-if="index.network != 'livenet'">
Testnet
<span ng-if="!index.canSign"> - <span translate>No Private key</span></span>
</div>
</div>
</div>
@ -160,9 +168,9 @@
</div>
<div class="text-gray text-center size-12 p10t"
ng-show="index.lockedBalance && !index.updatingStatus">
ng-show="index.lockedBalanceSat && !index.updatingStatus">
<span translate>Total Locked Balance</span>:
<b>{{index.lockedBalance}} {{index.unitName}} </b>
<b>{{index.lockedBalanceStr}} </b>
<span> {{index.lockedBalanceAlternative}}
{{index.alternativeIsoCode}} </span>
</div>
@ -286,12 +294,12 @@
<h4 class="title m0">
<a class="right lh"
ng-if="index.feeToSendMaxStr && index.availableBalance > 0 && !home.blockUx && !home.lockAmount"
ng-click="home.sendAll(index.availableMaxBalance, index.feeToSendMaxStr)"
ng-if="index.feeToSendMaxStr && index.availableBalanceSat > 0 && !home.blockUx && !home.lockAmount"
ng-click="home.sendAll(index.availableMaxBalance, index.feeToSendMaxStr, index.feeRateToSendMax)"
translate> Send All
</a>
<div ng-show="!index.lockedBalance && index.availableBalanceStr">
<div ng-show="!index.lockedBalanceSat && index.availableBalanceStr">
<div class="size-10">
<span class="db text-bold">
<span translate>Available Balance</span>:
@ -299,7 +307,7 @@
</span>
</div>
</div>
<div ng-show="index.lockedBalance">
<div ng-show="index.lockedBalanceSat">
<div class="left">
<i class="fi-info size-24 m10r"></i>
</div>
@ -371,7 +379,7 @@
<i class="icon-close-circle size-14"></i>
<span clas="vm" translate>Not valid</span>
</span>
<small class="text-primary right" ng-if="!sendForm.amount.$invalid">
<small class="text-primary right" ng-if="!sendForm.amount.$invalid && !sendForm.alternative.$invalid">
<i class="icon-checkmark-circle size-14"></i>
</small>
</div>
@ -389,7 +397,7 @@
<label for="alternative"><span translate>Amount in</span> {{ home.alternativeName }}
</label>
<div class="input">
<input type="number" id="alternative" ng-disabled="home.blockUx || !home.isRateAvailable || home.lockAmount" name="alternative" ng-attr-placeholder="{{'Amount'|translate}}" ng-model="_alternative" requiredautocomplete="off" ng-focus="home.formFocus('amount')" ng-blur="home.formFocus(false)">
<input type="number" id="alternative" ng-disabled="home.blockUx || !home.isRateAvailable || home.lockAmount" name="alternative" ng-attr-placeholder="{{'Amount'|translate}}" ng-model="_alternative" required autocomplete="off" ng-focus="home.formFocus('amount')" ng-blur="home.formFocus(false)">
<input type="number" id="amount" name="amount" ng-model="_amount" style="display:none">
<a class="postfix" ng-click="home.hideAlternative()"> {{ home.alternativeIsoCode }}</a>
</div>
@ -410,6 +418,35 @@
</div>
</div>
<div class="m20b" ng-init="home.hideAdvSend=true">
<a class="button outline light-gray expand tiny m0" ng-click="home.hideAdvSend=!home.hideAdvSend">
<i class="fi-widget m3r"></i>
<span translate ng-hide="!home.hideAdvSend">Show advanced options</span>
<span translate ng-hide="home.hideAdvSend">Hide advanced options</span>
<i ng-if="home.hideAdvSend" class="icon-arrow-down4"></i>
<i ng-if="!home.hideAdvSend" class="icon-arrow-up4"></i>
</a>
<div class="m10t" ng-hide="home.hideAdvSend">
<div ng-show="(index.network == 'livenet' ? index.feeLevels.livenet : index.feeLevels.testnet)">
<h4 class="title m0" translate>Fee policy for this transaction</h4>
<ul class="no-bullet m0 size-14">
<li ng-repeat="fee in (index.network == 'livenet' ? index.feeLevels.livenet : index.feeLevels.testnet)"
ng-click="home.setFee(fee.level)" class="line-b p20">
{{index.feeOpts[fee.level]|translate}}
<i class="fi-check size-16 right"
ng-show="(home.currentSendFeeLevel || index.currentFeeLevel) == fee.level"></i>
</li>
</ul>
</div>
<h4 class="title m0">&nbsp;</h4>
<div class="p20 line-b">
<span class="size-14" translate>Use Unconfirmed Funds</span>
<switch id="spend-unconfirmed" name="currentSpendUnconfirmed" ng-model="currentSpendUnconfirmed" class="green right"></switch>
</div>
</div>
</div>
<div class="row" ng-show="!home.onGoingProcess">
<div class="large-6 medium-6 small-6 columns" ng-show="!home.blockUx && (home._paypro || home.lockAddress || home.lockAmount)">
<a ng-click="home.resetForm(sendForm)" class="button expand outline dark-gray round" translate>Cancel</a>
@ -456,14 +493,19 @@
ng-style="{'background-color':index.backgroundColor}" translate>Received</span>
<span class="label tu gray radius" ng-show="btx.action == 'sent'" translate>Sent</span>
<span class="label tu gray radius" ng-show="btx.action == 'moved'" translate>Moved</span>
<span class="label tu warning radius" ng-show="btx.action == 'invalid'" translate>Invalid</span>
</div>
<div class="large-4 medium-4 small-4 columns">
<span class="size-16">
<span ng-if="btx.action == 'received'">+</span>
<span ng-if="btx.action == 'sent'">-</span>
<span class="size-12" ng-if="btx.action == 'invalid'" translate>
(possible double spend)
</span>
<span ng-if="btx.action != 'invalid'">
{{btx.amountStr}}
{{home.getUnitName()}}
</span>
</span>
</div>
<div class="large-4 medium-4 small-4 columns text-right">
@ -509,6 +551,9 @@
<div class="extra-margin-bottom"></div>
</div> <!-- END History -->
<div id="{{view.id}}" class="{{view.class}} tab-view" ng-repeat="view in index.addonViews" ng-include="view.template">
</div>
</div>
</div>
<div class="extra-margin-bottom"></div>

View File

@ -168,12 +168,6 @@ input:-webkit-autofill, textarea:-webkit-autofill, select:-webkit-autofill, inpu
top: 0;
}
.logo-setup {
text-align: center;
margin: 0 0 0.1rem 0;
color: #8597A7;
}
.box-setup-footer {
overflow: hidden;
margin-top: 1rem;
@ -522,11 +516,6 @@ ul.pagination li.current a {
background: #1ABC9C;
}
.logo {
background: transparent url('../img/logo-negative-beta.svg') no-repeat;
background-size: 130px 51px;
}
input {
border-radius: 2px;
background: #EDEDED;
@ -877,6 +866,7 @@ input.ng-invalid-match, input.ng-invalid-match:focus {
.text-alert {color: red;}
.text-success {color: #1ABC9C;}
.text-spacing {letter-spacing:2px;}
.text-capitalize {text-transform: capitalize;}
.panel {
background: #FFFFFF;
@ -1084,20 +1074,13 @@ input.ng-invalid-match, input.ng-invalid-match:focus {
}
.splash {
width: 100%;
height: 100%;
top: 0;
background: #2C3E50;
position: absolute;
background-image: -webkit-linear-gradient(#3D5672 0%, #223243 100%);
background-image: -o-linear-gradient(#3D5672 0%, #223243 100%);
background-image: linear-gradient(#3D5672 0%, #223243 100%);
}
.splash .start-button {
position: absolute;
bottom: 0;
}
.splash .start-button button.black {
background-color: #4B6178;
}
@ -1106,7 +1089,7 @@ input.ng-invalid-match, input.ng-invalid-match:focus {
font-size: 0.58rem;
}
.gif-splash {
.splash .container-image {
padding: 2rem 0;
}
@ -1118,6 +1101,17 @@ input.ng-invalid-match, input.ng-invalid-match:focus {
padding: 0.6rem 0.8rem !important;
}
.alertModal {
background: #FFFFFF;
box-shadow: 0px 0px 6px 0px rgba(0,0,0,0.50);
border-radius: 5px;
position: absolute;
width: 90%;
left: 5%;
top: 15%;
z-index: 1100;
}
.passModal {
background: #FFFFFF;
box-shadow: 0px 0px 6px 0px rgba(0,0,0,0.50);

View File

@ -151,10 +151,24 @@ _:-ms-fullscreen, :root .main {
background: #2C3E50;
}
.second-bottom-bar {
z-index: 6;
}
.second-bottom-bar.animated.slideInRight,
.second-bottom-bar.animated.slideInLeft {
-webkit-animation-duration: 0.3s;
animation-duration: 0.3s;
}
.menu-toggle {
padding-top: 1rem !important;
}
.amount {
width: 100%;
text-align: center;
padding: 3rem 1rem;
padding: 2.5rem 1rem 1.5rem 1rem;
margin-bottom: 11px;
color: #fff;
height: 175px;
@ -184,7 +198,7 @@ _:-ms-fullscreen, :root .main {
}
.walletHome .avatar-wallet {
padding: 1.7rem 1rem;
padding: 0.5rem;
width: 75px;
height: 75px;
position: absolute;
@ -195,7 +209,6 @@ _:-ms-fullscreen, :root .main {
margin: 0;
color: #FFF;
font-weight: 700;
line-height: 15px;
text-align: center;
border-radius: 5px;
}
@ -291,13 +304,12 @@ a.missing-copayers {
font-size: 20px;
font-weight: 700;
margin-right: 15px;
padding: 0.33rem 0.65rem;
line-height: 24px;
text-align: center;
float: left;
width: 35px;
height: 35px;
border-radius: 3px;
padding: 2px;
}
.sidebar header {
@ -326,7 +338,6 @@ a.missing-copayers {
border-bottom: transparent;
color: #A5B2BF;
padding: 1rem 0.7rem;
line-height: 155%;
}
.sidebar ul.off-canvas-list li a i {
@ -573,6 +584,7 @@ to prevent collapsing during animation*/
body.modal-open {
position: fixed;
overflow: hidden;
z-index: 1;
}
.reveal-modal {

View File

@ -12,7 +12,8 @@ var modules = [
'copayApp.filters',
'copayApp.services',
'copayApp.controllers',
'copayApp.directives'
'copayApp.directives',
'copayApp.addons'
];
var copayApp = window.copayApp = angular.module('copayApp', modules);
@ -21,3 +22,5 @@ angular.module('copayApp.filters', []);
angular.module('copayApp.services', []);
angular.module('copayApp.controllers', []);
angular.module('copayApp.directives', []);
angular.module('copayApp.addons', []);

View File

@ -1,7 +1,7 @@
'use strict';
angular.module('copayApp.controllers').controller('backupController',
function($rootScope, $scope, $timeout, backupService, profileService, isMobile, isCordova, notification, go, gettext) {
function($rootScope, $scope, $timeout, backupService, profileService, isMobile, isCordova, notification, go, gettext, gettextCatalog) {
this.isSafari = isMobile.Safari();
this.isCordova = isCordova;
this.error = null;
@ -11,7 +11,15 @@ angular.module('copayApp.controllers').controller('backupController',
this.isEncrypted = fc.isPrivKeyEncrypted();
this.downloadWalletBackup = function() {
backupService.walletDownload(this.password, function() {
var self = this;
var opts = {
noSign: $scope.noSign,
};
backupService.walletDownload(this.password, opts, function(err) {
if (err) {
self.error = true;
return ;
}
$rootScope.$emit('Local/BackupDone');
notification.success(gettext('Backup created'), gettext('Encrypted backup file saved'));
go.walletHome();
@ -19,21 +27,34 @@ angular.module('copayApp.controllers').controller('backupController',
};
this.getBackup = function() {
return backupService.walletExport(this.password);
var opts = {
noSign: $scope.noSign,
};
var ew = backupService.walletExport(this.password, opts);
if (!ew) {
this.error = true;
} else {
this.error = false;
}
return ew;
};
this.viewWalletBackup = function() {
var self = this;
$timeout(function() {
self.backupWalletPlainText = self.getBackup();
var ew = self.getBackup();
if (!ew) return;
self.backupWalletPlainText = ew;
$rootScope.$emit('Local/BackupDone');
}, 100);
};
this.copyWalletBackup = function() {
var ew = this.getBackup();
if (!ew) return;
window.cordova.plugins.clipboard.copy(ew);
window.plugins.toast.showShortCenter('Copied to clipboard');
window.plugins.toast.showShortCenter(gettextCatalog.getString('Copied to clipboard'));
$rootScope.$emit('Local/BackupDone');
};
@ -42,12 +63,17 @@ angular.module('copayApp.controllers').controller('backupController',
if (isMobile.Android() || isMobile.Windows()) {
window.ignoreMobilePause = true;
}
window.plugins.toast.showShortCenter('Preparing backup...');
window.plugins.toast.showShortCenter(gettextCatalog.getString('Preparing backup...'));
var name = (fc.credentials.walletName || fc.credentials.walletId);
if (fc.alias) {
name = fc.alias + ' [' + name + ']';
}
var ew = this.getBackup();
if (!ew) return;
if( $scope.noSign)
name = name + '(No Private Key)';
var properties = {
subject: 'Copay Wallet Backup: ' + name,
body: 'Here is the encrypted backup of the wallet ' + name + ': \n\n' + ew + '\n\n To import this backup, copy all text between {...}, including the symbols {}',

View File

@ -4,6 +4,10 @@ angular.module('copayApp.controllers').controller('copayersController',
function($scope, $rootScope, $timeout, $log, $modal, profileService, go, notification, isCordova, gettext, gettextCatalog) {
var self = this;
var delete_msg = gettextCatalog.getString('Are you sure you want to delete this wallet?');
var accept_msg = gettextCatalog.getString('Accept');
var cancel_msg = gettextCatalog.getString('Cancel');
var confirm_msg = gettextCatalog.getString('Confirm');
self.init = function() {
var fc = profileService.focusedClient;
@ -18,16 +22,16 @@ angular.module('copayApp.controllers').controller('copayersController',
var _modalDeleteWallet = function() {
var ModalInstanceCtrl = function($scope, $modalInstance, gettext) {
$scope.title = gettext('Are you sure you want to delete this wallet?');
$scope.title = delete_msg;
$scope.loading = false;
$scope.ok = function() {
$scope.loading = true;
$modalInstance.close('ok');
$modalInstance.close(accept_msg);
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
$modalInstance.dismiss(cancel_msg);
};
};
@ -59,7 +63,7 @@ angular.module('copayApp.controllers').controller('copayersController',
} else {
go.walletHome();
$timeout(function() {
notification.success(gettext('Success'), gettextCatalog.getString('The wallet "{{walletName}}" was deleted', {walletName: walletName}));
notification.success(gettextCatalog.getString('Success'), gettextCatalog.getString('The wallet "{{walletName}}" was deleted', {walletName: walletName}));
});
}
});
@ -70,13 +74,13 @@ angular.module('copayApp.controllers').controller('copayersController',
var fc = profileService.focusedClient;
if (isCordova) {
navigator.notification.confirm(
'Are you sure you want to delete this wallet?',
delete_msg,
function(buttonIndex) {
if (buttonIndex == 2) {
if (buttonIndex == 1) {
_deleteWallet();
}
},
'Confirm', ['Cancel', 'OK']
confirm_msg, [accept_msg, cancel_msg]
);
} else {
_modalDeleteWallet();
@ -86,7 +90,7 @@ angular.module('copayApp.controllers').controller('copayersController',
self.copySecret = function(secret) {
if (isCordova) {
window.cordova.plugins.clipboard.copy(secret);
window.plugins.toast.showShortCenter('Copied to clipboard');
window.plugins.toast.showShortCenter(gettextCatalog.getString('Copied to clipboard'));
}
};
@ -95,8 +99,8 @@ angular.module('copayApp.controllers').controller('copayersController',
if (isMobile.Android() || isMobile.Windows()) {
window.ignoreMobilePause = true;
}
var message = 'Join my Copay wallet. Here is the invitation code: ' + secret + ' You can download Copay for your phone or desktop at https://copay.io';
window.plugins.socialsharing.share(message, 'Invitation to share a Copay Wallet', null, null);
var message = gettextCatalog.getString('Join my Copay wallet. Here is the invitation code: {{secret}} You can download Copay for your phone or desktop at https://copay.io', {secret: secret});
window.plugins.socialsharing.share(message, gettextCatalog.getString('Invitation to share a Copay Wallet'), null, null);
}
};

View File

@ -63,6 +63,9 @@ angular.module('copayApp.controllers').controller('createController',
if (err) {
$log.debug(err);
self.error = err;
$timeout(function() {
$rootScope.$apply();
});
}
else {
go.walletHome();

View File

@ -1,6 +1,6 @@
'use strict';
angular.module('copayApp.controllers').controller('indexController', function($rootScope, $scope, $log, $filter, $timeout, lodash, go, profileService, configService, isCordova, rateService, storageService, addressService, gettextCatalog, gettext, amMoment, nodeWebkit) {
angular.module('copayApp.controllers').controller('indexController', function($rootScope, $scope, $log, $filter, $timeout, lodash, go, profileService, configService, isCordova, rateService, storageService, addressService, gettextCatalog, gettext, amMoment, nodeWebkit, addonManager, feeService, isChromeApp, bwsError, utilService) {
var self = this;
self.isCordova = isCordova;
self.onGoingProcess = {};
@ -10,12 +10,10 @@ angular.module('copayApp.controllers').controller('indexController', function($r
return (parseFloat(number.toPrecision(12)));
};
self.goHome = function() {
go.walletHome();
};
self.menu = [{
'title': gettext('Home'),
'icon': 'icon-home',
@ -34,28 +32,43 @@ angular.module('copayApp.controllers').controller('indexController', function($r
'link': 'history'
}];
self.addonViews = addonManager.addonViews();
self.menu = self.menu.concat(addonManager.addonMenuItems());
self.menuItemSize = self.menu.length > 4 ? 2 : 3;
self.tab = 'walletHome';
self.availableLanguages = [{
name: gettext('Deutsch'),
isoCode: 'de',
}, {
name: gettext('English'),
name: 'English',
isoCode: 'en',
}, {
name: gettext('Spanish'),
isoCode: 'es',
}, {
name: gettext('French'),
name: 'Français',
isoCode: 'fr',
}, {
name: gettext('Japanese'),
name: 'Italiano',
isoCode: 'it',
}, {
name: 'Deutsch',
isoCode: 'de',
}, {
name: 'Español',
isoCode: 'es',
}, {
name: 'Português',
isoCode: 'pt',
}, {
name: 'Ελληνικά',
isoCode: 'el',
}, {
name: '日本語',
isoCode: 'ja',
}, {
name: gettext('Portuguese'),
isoCode: 'pt',
name: 'Pусский',
isoCode: 'ru',
}];
self.feeOpts = feeService.feeOpts;
self.setOngoingProcess = function(processName, isOn) {
$log.debug('onGoingProcess', processName, isOn);
self[processName] = isOn;
@ -79,17 +92,26 @@ angular.module('copayApp.controllers').controller('indexController', function($r
if (!fc) return;
// Clean status
self.lockedBalance = null;
self.totalBalanceSat = null;
self.lockedBalanceSat = null;
self.availableBalanceSat = null;
self.pendingAmount = null;
self.spendUnconfirmed = null;
self.totalBalanceStr = null;
self.availableBalanceStr = null;
self.totalBalanceStr = null;
self.lockedBalanceStr = null;
self.totalBalanceStr = null;
self.alternativeBalanceAvailable = false;
self.totalBalanceAlternative = null;
self.currentFeeLevel = null;
self.notAuthorized = false;
self.txHistory = [];
self.txHistoryPaging = false;
self.pendingTxProposalsCountForUs = null;
self.setSpendUnconfirmed();
$timeout(function() {
self.hasProfile = true;
self.noFocusedWallet = false;
@ -106,6 +128,7 @@ angular.module('copayApp.controllers').controller('indexController', function($r
self.walletName = fc.credentials.walletName;
self.walletId = fc.credentials.walletId;
self.isComplete = fc.isComplete();
self.canSign = fc.canSign();
self.txps = [];
self.copayers = [];
self.updateColor();
@ -226,7 +249,7 @@ angular.module('copayApp.controllers').controller('indexController', function($r
self.updateError = false;
return fc.getStatus(function(err, ret) {
if (err) {
self.updateError = true;
self.updateError = bwsError.msg(err, gettext('Could not update Wallet'));
} else {
if (!opts.quiet)
self.setOngoingProcess('scanning', ret.wallet.scanning);
@ -267,6 +290,7 @@ angular.module('copayApp.controllers').controller('indexController', function($r
}
$log.debug('Wallet Status:', walletStatus);
self.setPendingTxps(walletStatus.pendingTxps);
self.setFeesOpts();
// Status Shortcuts
self.walletName = walletStatus.wallet.name;
@ -279,6 +303,10 @@ angular.module('copayApp.controllers').controller('indexController', function($r
self.otherWallets = lodash.filter(profileService.getWallets(self.network), function(w) {
return w.id != self.walletId;
});;
// Notify external addons or plugins
$rootScope.$emit('Local/BalanceUpdated', walletStatus.balance);
$rootScope.$apply();
if (opts.triggerTxUpdate) {
@ -290,6 +318,48 @@ angular.module('copayApp.controllers').controller('indexController', function($r
});
};
self.setSpendUnconfirmed = function() {
self.spendUnconfirmed = configService.getSync().wallet.spendUnconfirmed;
};
self.setSendMax = function() {
// Set Send max
if (self.currentFeeLevel && self.totalBytesToSendMax) {
feeService.getCurrentFeeValue(self.currentFeeLevel, function(err, feePerKb) {
// KB to send max
if (self.totalBytesToSendMax) {
var feeToSendMaxSat = parseInt(((self.totalBytesToSendMax * feePerKb) / 1000.).toFixed(0));
self.feeRateToSendMax = feePerKb;
self.availableMaxBalance = strip((self.availableBalanceSat - feeToSendMaxSat) * self.satToUnit);
self.feeToSendMaxStr = profileService.formatAmount(feeToSendMaxSat) + ' ' + self.unitName;
} else {
self.feeToSendMaxStr = null;
self.feeRateToSendMax = null;
}
});
}
};
self.setCurrentFeeLevel = function(level) {
self.currentFeeLevel = level || configService.getSync().wallet.settings.feeLevel || 'normal';
self.setSendMax();
};
self.setFeesOpts = function() {
var fc = profileService.focusedClient;
if (!fc) return;
$timeout(function() {
feeService.getFeeLevels(function(levels) {
self.feeLevels = levels;
$rootScope.$apply();
});
});
};
self.updateBalance = function() {
var fc = profileService.focusedClient;
$timeout(function() {
@ -298,8 +368,7 @@ angular.module('copayApp.controllers').controller('indexController', function($r
fc.getBalance(function(err, balance) {
self.setOngoingProcess('updatingBalance', false);
if (err) {
$log.debug('Wallet Balance ERROR:', err);
$scope.$emit('Local/ClientError', err);
self.handleError(err);
return;
}
$log.debug('Wallet Balance:', balance);
@ -316,8 +385,7 @@ angular.module('copayApp.controllers').controller('indexController', function($r
fc.getTxProposals({}, function(err, txps) {
self.setOngoingProcess('updatingPendingTxps', false);
if (err) {
$log.debug('Wallet PendingTxps ERROR:', err);
$scope.$emit('Local/ClientError', err);
self.handleError(err);
} else {
$log.debug('Wallet PendingTxps:', txps);
self.setPendingTxps(txps);
@ -330,7 +398,6 @@ angular.module('copayApp.controllers').controller('indexController', function($r
self.updateTxHistory = function(skip) {
var fc = profileService.focusedClient;
if (!fc.isComplete()) return;
if (!skip) {
self.txHistory = [];
}
@ -339,6 +406,7 @@ angular.module('copayApp.controllers').controller('indexController', function($r
self.txHistoryError = false;
self.updatingTxHistory = true;
self.txHistoryPaging = false;
$timeout(function() {
fc.getTxHistory({
skip: self.skipHistory,
@ -348,8 +416,10 @@ angular.module('copayApp.controllers').controller('indexController', function($r
if (err) {
$log.debug('TxHistory ERROR:', err);
// We do not should errors here, since history is usually
// fetched AFTER others requests.
//self.handleError(err);
// fetched AFTER others requests (if skip=0)
if (skip)
self.handleError(err);
self.txHistoryError = true;
} else {
$log.debug('Wallet Transaction History:', txs);
@ -361,14 +431,20 @@ angular.module('copayApp.controllers').controller('indexController', function($r
});
};
// This handles errors from BWS/index with are nomally
// trigger from async events (like updates)
self.handleError = function(err) {
$log.warn('Client ERROR:', err);
if (err.code === 'NOTAUTHORIZED') {
$scope.$emit('Local/NotAuthorized');
} else if (err.code === 'NOTFOUND') {
$scope.$emit('Local/BWSNotFound');
if (err.code === 'NOT_AUTHORIZED') {
self.notAuthorized = true;
go.walletHome();
} else if (err.code === 'NOT_FOUND') {
self.showErrorPopup(gettext('Could not access Wallet Service: Not found'));
} else {
var msg = ""
$scope.$emit('Local/ClientError', (err.error ? err.error : err));
var msg = bwsError.msg(err, gettext('Error at Wallet Service'));
self.showErrorPopup(msg);
}
};
self.openWallet = function() {
@ -394,17 +470,10 @@ angular.module('copayApp.controllers').controller('indexController', function($r
};
self.setPendingTxps = function(txps) {
var config = configService.getSync().wallet.settings;
self.pendingTxProposalsCountForUs = 0;
lodash.each(txps, function(tx) {
var amount = tx.amount * self.satToUnit;
tx.amountStr = profileService.formatAmount(tx.amount) + ' ' + config.unitName;
tx.feeStr = profileService.formatAmount(tx.fee) + ' ' + config.unitName;
tx.alternativeAmount = rateService.toFiat(tx.amount, config.alternativeIsoCode) ? rateService.toFiat(tx.amount, config.alternativeIsoCode).toFixed(2) : 'N/A';
tx.alternativeAmountStr = tx.alternativeAmount + " " + config.alternativeIsoCode;
tx.alternativeIsoCode = config.alternativeIsoCode;
tx = utilService.processTx(tx);
var action = lodash.find(tx.actions, {
copayerId: self.copayerId
@ -428,22 +497,23 @@ angular.module('copayApp.controllers').controller('indexController', function($r
if (tx.creatorId != self.copayerId) {
self.pendingTxProposalsCountForUs = self.pendingTxProposalsCountForUs + 1;
}
addonManager.formatPendingTxp(tx);
});
self.txps = txps;
};
self.setTxHistory = function(txs) {
var config = configService.getSync().wallet.settings;
var now = Math.floor(Date.now() / 1000);
var c = 0;
self.txHistoryPaging = txs[self.limitHistory] ? true : false;
lodash.each(txs, function(tx) {
tx = utilService.processTx(tx);
// no future transactions...
if (tx.time > now)
tx.time = now;
tx.rateTs = Math.floor((tx.ts || now) / 1000);
tx.amountStr = profileService.formatAmount(tx.amount); //$filter('noFractionNumber')(
if (c < self.limitHistory) {
self.txHistory.push(tx);
c++;
@ -472,47 +542,46 @@ angular.module('copayApp.controllers').controller('indexController', function($r
var config = configService.getSync().wallet.settings;
var COIN = 1e8;
// Address with Balance
self.balanceByAddress = balance.byAddress;
// SAT
self.totalBalanceSat = balance.totalAmount;
self.lockedBalanceSat = balance.lockedAmount;
self.availableBalanceSat = self.totalBalanceSat - self.lockedBalanceSat;
if (self.spendUnconfirmed) {
self.totalBalanceSat = balance.totalAmount;
self.lockedBalanceSat = balance.lockedAmount;
self.availableBalanceSat = balance.availableAmount;
self.pendingAmount = null;
} else {
self.totalBalanceSat = balance.totalConfirmedAmount;
self.lockedBalanceSat = balance.lockedConfirmedAmount;
self.availableBalanceSat = balance.availableConfirmedAmount;
self.pendingAmount = balance.totalAmount - balance.totalConfirmedAmount;
}
// Selected unit
self.unitToSatoshi = config.unitToSatoshi;
self.satToUnit = 1 / self.unitToSatoshi;
self.unitName = config.unitName;
self.totalBalance = strip(self.totalBalanceSat * self.satToUnit);
self.lockedBalance = strip(self.lockedBalanceSat * self.satToUnit);
self.availableBalance = strip(self.availableBalanceSat * self.satToUnit);
// BTC
self.totalBalanceBTC = strip(self.totalBalanceSat / COIN);
self.lockedBalanceBTC = strip(self.lockedBalanceSat / COIN);
self.availableBalanceBTC = strip(self.availableBalanceBTC / COIN);
// KB to send max
self.feePerKbSat = config.feeValue || 10000;
if (balance.totalKbToSendMax) {
var feeToSendMaxSat = balance.totalKbToSendMax * self.feePerKbSat;
self.availableMaxBalance = strip((self.availableBalanceSat - feeToSendMaxSat) * self.satToUnit);
self.feeToSendMaxStr = profileService.formatAmount(feeToSendMaxSat) + ' ' + self.unitName;
} else {
self.feeToSendMaxStr = null;
}
//STR
self.totalBalanceStr = profileService.formatAmount(self.totalBalanceSat) + ' ' + self.unitName;
self.lockedBalanceStr = profileService.formatAmount(self.lockedBalanceSat) + ' ' + self.unitName;
self.availableBalanceStr = profileService.formatAmount(self.availableBalanceSat) + ' ' + self.unitName;
if (self.pendingAmount) {
self.pendingAmountStr = profileService.formatAmount(self.pendingAmount) + ' ' + self.unitName;
} else {
self.pendingAmountStr = null;
}
self.alternativeName = config.alternativeName;
self.alternativeIsoCode = config.alternativeIsoCode;
// Other
self.totalBytesToSendMax = balance.totalBytesToSendMax;
self.setCurrentFeeLevel();
// Check address
addressService.isUsed(self.walletId, balance.byAddress, function(err, used) {
if (used) {
@ -523,8 +592,8 @@ angular.module('copayApp.controllers').controller('indexController', function($r
rateService.whenAvailable(function() {
var totalBalanceAlternative = rateService.toFiat(self.totalBalance * self.unitToSatoshi, self.alternativeIsoCode);
var lockedBalanceAlternative = rateService.toFiat(self.lockedBalance * self.unitToSatoshi, self.alternativeIsoCode);
var totalBalanceAlternative = rateService.toFiat(self.totalBalanceSat, self.alternativeIsoCode);
var lockedBalanceAlternative = rateService.toFiat(self.lockedBalanceSat, self.alternativeIsoCode);
var alternativeConversionRate = rateService.toFiat(100000000, self.alternativeIsoCode);
self.totalBalanceAlternative = $filter('noFractionNumber')(totalBalanceAlternative, 2);
@ -555,7 +624,7 @@ angular.module('copayApp.controllers').controller('indexController', function($r
}
});
}, false);
chooser.click();
chooser.click();
}
function formatDate(date) {
@ -595,8 +664,7 @@ angular.module('copayApp.controllers').controller('indexController', function($r
if (txs && txs.length > 0) {
allTxs.push(txs);
return getHistory(skip + 100, cb);
}
else {
} else {
return cb(null, lodash.flatten(allTxs));
}
});
@ -617,30 +685,44 @@ angular.module('copayApp.controllers').controller('indexController', function($r
getHistory(null, function(err, txs) {
self.setOngoingProcess('generatingCSV', false);
if (err) {
$log.debug('TxHistory ERROR:', err);
self.handleError(err);
} else {
$log.debug('Wallet Transaction History:', txs);
self.satToUnit = 1 / self.unitToSatoshi;
var data = txs;
var satToBtc = 1 / 100000000;
var filename = 'Copay-' + (self.alias || self.walletName ) + '.csv';
var filename = 'Copay-' + (self.alias || self.walletName) + '.csv';
var csvContent = '';
if (!isNode) csvContent = 'data:text/csv;charset=utf-8,';
csvContent += 'Date,Destination,Note,Amount,Currency,Spot Value,Total Value,Tax Type,Category\n';
var _amount;
var _amount, _note;
var dataString;
data.forEach(function(it, index) {
_amount = (it.action == 'sent' ? '-' : '') + (it.amount * satToBtc).toFixed(8);
dataString = formatDate(it.time * 1000) + ',' + formatString(it.addressTo) + ',' + formatString(it.message) + ',' + _amount + ',BTC,,,,';
csvContent += index < data.length ? dataString + "\n" : dataString;
var amount = it.amount;
if (it.action == 'moved')
amount = 0;
_amount = (it.action == 'sent' ? '-' : '') + (amount * satToBtc).toFixed(8);
_note = formatString((it.message ? it.message : '') + ' TxId: ' + it.txid + ' Fee:' + (it.fees * satToBtc).toFixed(8));
if (it.action == 'moved')
_note += ' Moved:' + (it.amount * satToBtc).toFixed(8)
dataString = formatDate(it.time * 1000) + ',' + formatString(it.addressTo) + ',' + _note + ',' + _amount + ',BTC,,,,';
csvContent += dataString + "\n";
if (it.fees && (it.action == 'moved' || it.action == 'sent')) {
var _fee = (it.fees * satToBtc).toFixed(8)
csvContent += formatDate(it.time * 1000) + ',Bitcoin Network Fees,, -' + _fee + ',BTC,,,,' + "\n";
}
});
if (isNode) {
saveFile('#export_file', csvContent);
}
else {
} else {
var encodedUri = encodeURI(csvContent);
var link = document.createElement("a");
link.setAttribute("href", encodedUri);
@ -653,31 +735,21 @@ angular.module('copayApp.controllers').controller('indexController', function($r
});
};
self.clientError = function(err) {
if (isCordova) {
navigator.notification.confirm(
err,
function() {},
'Wallet Server Error', ['OK']
);
} else {
alert(err);
}
};
self.showErrorPopup = function (msg, cb) {
$log.warn('Showing err popup:' + msg);
self.showAlert = {
msg: msg,
close: function(err) {
self.showAlert = null;
if (cb) return cb(err);
},
};
$timeout(function() {
$rootScope.$apply();
});
self.deviceError = function(err) {
if (isCordova) {
navigator.notification.confirm(
err,
function() {},
'Device Error', ['OK']
);
} else {
alert(err);
}
};
self.recreate = function(cb) {
var fc = profileService.focusedClient;
self.setOngoingProcess('recreating', true);
@ -769,6 +841,15 @@ angular.module('copayApp.controllers').controller('indexController', function($r
});
});
$rootScope.$on('Local/SpendUnconfirmedUpdated', function(event) {
self.setSpendUnconfirmed();
self.updateAll();
});
$rootScope.$on('Local/FeeLevelUpdated', function(event, level) {
self.setCurrentFeeLevel(level);
});
$rootScope.$on('Local/ProfileBound', function() {
storageService.getRemotePrefsStoredFlag(function(err, val) {
if (err || val) return;
@ -807,7 +888,7 @@ angular.module('copayApp.controllers').controller('indexController', function($r
$rootScope.$on('Local/EmailSettingUpdated', function(event, email, cb) {
self.updateRemotePreferences({
preferences: {
email: email
email: email || null
},
}, cb);
});
@ -832,6 +913,9 @@ angular.module('copayApp.controllers').controller('indexController', function($r
trailing: true
});
self.debouncedUpdateHistory = lodash.throttle(function() {
self.updateTxHistory();
}, 60000);
$rootScope.$on('Local/Resume', function(event) {
$log.debug('### Resume event');
@ -841,41 +925,12 @@ angular.module('copayApp.controllers').controller('indexController', function($r
$rootScope.$on('Local/BackupDone', function(event) {
self.needsBackup = false;
storageService.setBackupFlag(self.walletId, function(err) {
if (err) $rootScope.$emit('Local/DeviceError', err)
if (err) root.showErrorPopup(err);
});
});
$rootScope.$on('Local/NotAuthorized', function(event) {
self.notAuthorized = true;
$rootScope.$apply();
});
$rootScope.$on('Local/BWSNotFound', function(event) {
self.clientError('Could not access Wallet Service: Not found');
$rootScope.$apply();
});
$rootScope.$on('Local/DeviceError', function(event, err) {
self.deviceError(err);
$rootScope.$apply();
});
$rootScope.$on('Local/ClientError', function(event, err) {
if (err.code && err.code === 'NOTAUTHORIZED') {
// Show not error, just redirect to home (where the recreate option is shown)
go.walletHome();
} else if (err && err.cors == 'rejected') {
$log.debug('CORS error:', err);
} else if (err.code === 'ETIMEDOUT' || err.code === 'CONNERROR') {
$log.debug('Time out:', err);
} else {
var msg = 'Error at Wallet Service: ';
if (err.message) msg = msg + err.message;
else if (err.error) msg = msg + err.error;
else msg = msg + (lodash.isObject(err) ? JSON.stringify(err) : err);
self.clientError(msg);
}
$rootScope.$apply();
root.showErrorPopup(err);
});
$rootScope.$on('Local/WalletImported', function(event, walletId) {
@ -895,6 +950,20 @@ angular.module('copayApp.controllers').controller('indexController', function($r
});
});
$rootScope.$on('NewBlock', function() {
if (self.pendingAmount) {
self.updateAll();
}
if (self.network == 'testnet') {
self.debouncedUpdateHistory();
} else {
self.updateTxHistory();
}
});
$rootScope.$on('NewOutgoingTx', function() {
self.updateAll({
walletStatus: null,
@ -960,6 +1029,10 @@ angular.module('copayApp.controllers').controller('indexController', function($r
self.setTab(tab, reset);
});
$rootScope.$on('Local/ShowAlert', function(event, msg, cb) {
self.showErrorPopup(msg,cb);
});
$rootScope.$on('Local/NeedsPassword', function(event, isSetup, cb) {
self.askPassword = {
isSetup: isSetup,

View File

@ -153,7 +153,7 @@ angular.module('copayApp.controllers').controller('joinController',
}, function(err) {
if (err) {
self.loading = false;
self.error = gettext('Could not join wallet: ') + (err.message ? err.message : err);
self.error = err;
$rootScope.$apply();
return
}

View File

@ -4,16 +4,29 @@ angular.module('copayApp.controllers').controller('preferencesController',
function($scope, $rootScope, $filter, $timeout, $modal, $log, lodash, configService, profileService) {
var config = configService.getSync();
this.unitName = config.wallet.settings.unitName;
this.feeName = config.wallet.settings.feeName || 'Priority';
this.bwsurl = config.bws.url;
this.selectedAlternative = {
name: config.wallet.settings.alternativeName,
isoCode: config.wallet.settings.alternativeIsoCode
};
$scope.spendUnconfirmed = config.wallet.spendUnconfirmed;
var fc = profileService.focusedClient;
if (fc)
$scope.encrypt = fc.hasPrivKeyEncrypted();
var unwatchSpendUnconfirmed = $scope.$watch('spendUnconfirmed', function(newVal, oldVal) {
if (newVal == oldVal) return;
var opts = {
wallet: {
spendUnconfirmed: newVal
}
};
configService.set(opts, function(err) {
$rootScope.$emit('Local/SpendUnconfirmedUpdated');
if (err) $log.debug(err);
});
});
var unwatch = $scope.$watch('encrypt', function(val) {
var fc = profileService.focusedClient;
if (!fc) return;
@ -50,5 +63,6 @@ angular.module('copayApp.controllers').controller('preferencesController',
$scope.$on('$destroy', function() {
unwatch();
unwatchSpendUnconfirmed();
});
});

View File

@ -4,6 +4,7 @@ angular.module('copayApp.controllers').controller('preferencesColorController',
function($scope, configService, profileService, go) {
var config = configService.getSync();
this.colorOpts = [
'#DD4B39',
'#F38F12',
'#FAA77F',
'#FADA58',

View File

@ -5,18 +5,23 @@ angular.module('copayApp.controllers').controller('preferencesDeleteWalletContro
this.isCordova = isCordova;
this.error = null;
var delete_msg = gettextCatalog.getString('Are you sure you want to delete this wallet?');
var accept_msg = gettextCatalog.getString('Accept');
var cancel_msg = gettextCatalog.getString('Cancel');
var confirm_msg = gettextCatalog.getString('Confirm');
var _modalDeleteWallet = function() {
var ModalInstanceCtrl = function($scope, $modalInstance, gettext) {
$scope.title = gettext('Are you sure you want to delete this wallet?');
$scope.title = delete_msg;
$scope.loading = false;
$scope.ok = function() {
$scope.loading = true;
$modalInstance.close('ok');
$modalInstance.close(accept_msg);
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
$modalInstance.dismiss(cancel_msg);
};
};
@ -42,7 +47,7 @@ angular.module('copayApp.controllers').controller('preferencesDeleteWalletContro
if (err) {
self.error = err.message || err;
} else {
notification.success(gettext('Success'), gettextCatalog.getString('The wallet "{{walletName}}" was deleted', {walletName: name}));
notification.success(gettextCatalog.getString('Success'), gettextCatalog.getString('The wallet "{{walletName}}" was deleted', {walletName: walletName}));
}
});
};
@ -50,13 +55,13 @@ angular.module('copayApp.controllers').controller('preferencesDeleteWalletContro
this.deleteWallet = function() {
if (isCordova) {
navigator.notification.confirm(
'Are you sure you want to delete this wallet?',
delete_msg,
function(buttonIndex) {
if (buttonIndex == 2) {
if (buttonIndex == 1) {
_deleteWallet();
}
},
'Confirm', ['Cancel', 'OK']
confirm_msg, [accept_msg, cancel_msg]
);
} else {
_modalDeleteWallet();

View File

@ -1,37 +1,20 @@
'use strict';
angular.module('copayApp.controllers').controller('preferencesFeeController',
function($rootScope, $scope, configService, go, gettext) {
var config = configService.getSync();
this.feeName = config.wallet.settings.feeName || 'Priority';
this.feeOpts = [{
name: gettext('Priority'),
value: 100,
}, {
name: gettext('Normal'),
value: 50,
}, {
name: gettext('Economy'),
value: 10,
}, {
name: gettext('Emergency'),
red: true,
value: 500,
}, ];
function($rootScope, configService) {
this.save = function(newFee) {
var opts = {
wallet: {
settings: {
feeName: newFee.name,
feeValue: newFee.value * 100,
feeLevel: newFee
}
}
};
this.feeName = newFee.name;
$rootScope.$emit('Local/FeeLevelUpdated', newFee);
configService.set(opts, function(err) {
if (err) console.log(err);
if (err) $log.debug(err);
});
};

View File

@ -1,133 +1,13 @@
'use strict';
angular.module('copayApp.controllers').controller('topbarController', function($rootScope, $scope, $timeout, $modal, isCordova, isMobile, go) {
var cordovaOpenScanner = function() {
window.ignoreMobilePause = true;
window.plugins.spinnerDialog.show(null, 'Preparing camera...', true);
$timeout(function() {
cordova.plugins.barcodeScanner.scan(
function onSuccess(result) {
$timeout(function() {
window.plugins.spinnerDialog.hide();
window.ignoreMobilePause = false;
}, 100);
if (result.cancelled) return;
$timeout(function() {
var data = result.text;
$rootScope.$emit('dataScanned', data);
}, 1000);
},
function onError(error) {
$timeout(function() {
window.ignoreMobilePause = false;
window.plugins.spinnerDialog.hide();
}, 100);
alert('Scanning error');
}
);
go.send();
}, 100);
};
var modalOpenScanner = function() {
var _scope = $scope;
var ModalInstanceCtrl = function($scope, $rootScope, $modalInstance) {
// QR code Scanner
var video;
var canvas;
var $video;
var context;
var localMediaStream;
var _scan = function(evt) {
if (localMediaStream) {
context.drawImage(video, 0, 0, 300, 225);
try {
qrcode.decode();
} catch (e) {
//qrcodeError(e);
}
}
$timeout(_scan, 500);
};
var _scanStop = function() {
if (localMediaStream && localMediaStream.stop) localMediaStream.stop();
localMediaStream = null;
video.src = '';
};
qrcode.callback = function(data) {
_scanStop();
$modalInstance.close(data);
};
var _successCallback = function(stream) {
video.src = (window.URL && window.URL.createObjectURL(stream)) || stream;
localMediaStream = stream;
video.play();
$timeout(_scan, 1000);
};
var _videoError = function(err) {
$scope.cancel();
};
var setScanner = function() {
navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia || navigator.mozGetUserMedia ||
navigator.msGetUserMedia;
window.URL = window.URL || window.webkitURL ||
window.mozURL || window.msURL;
};
$scope.init = function() {
setScanner();
$timeout(function() {
go.send();
canvas = document.getElementById('qr-canvas');
context = canvas.getContext('2d');
video = document.getElementById('qrcode-scanner-video');
$video = angular.element(video);
canvas.width = 300;
canvas.height = 225;
context.clearRect(0, 0, 300, 225);
navigator.getUserMedia({
video: true
}, _successCallback, _videoError);
}, 500);
};
$scope.cancel = function() {
_scanStop();
$modalInstance.dismiss('cancel');
};
};
var modalInstance = $modal.open({
templateUrl: 'views/modals/scanner.html',
windowClass: 'full',
controller: ModalInstanceCtrl,
backdrop : 'static',
keyboard: false
});
modalInstance.result.then(function(data) {
$rootScope.$emit('dataScanned', data);
});
angular.module('copayApp.controllers').controller('topbarController', function($rootScope, go) {
this.onQrCodeScanned = function(data) {
$rootScope.$emit('dataScanned', data);
};
this.openScanner = function() {
if (isCordova) {
cordovaOpenScanner();
}
else {
modalOpenScanner();
}
this.openSendScreen = function() {
go.send();
};
this.goHome = function() {

View File

@ -1,10 +1,11 @@
'use strict';
angular.module('copayApp.controllers').controller('walletHomeController', function($scope, $rootScope, $timeout, $filter, $modal, $log, notification, txStatus, isCordova, profileService, lodash, configService, rateService, storageService, bitcore, isChromeApp, gettext, gettextCatalog, nodeWebkit, addressService) {
angular.module('copayApp.controllers').controller('walletHomeController', function($scope, $rootScope, $timeout, $filter, $modal, $log, notification, txStatus, isCordova, profileService, lodash, configService, rateService, storageService, bitcore, isChromeApp, gettext, gettextCatalog, nodeWebkit, addressService, feeService, bwsError, utilService) {
var self = this;
$rootScope.hideMenuBar = false;
$rootScope.wpInputFocused = false;
$scope.currentSpendUnconfirmed = configService.getSync().wallet.spendUnconfirmed;
// INIT
var config = configService.getSync().wallet.settings;
@ -28,6 +29,12 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
var disableScannerListener = $rootScope.$on('dataScanned', function(event, data) {
self.setForm(data);
$rootScope.$emit('Local/SetTab', 'send');
var form = $scope.sendForm;
if (form.address.$invalid) {
self.resetForm();
self.error = gettext('Could not recognize a valid Bitcoin QR Code');
}
});
var disablePaymentUriListener = $rootScope.$on('paymentUri', function(event, uri) {
@ -63,6 +70,10 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
};
});
var disableOngoingProcessListener = $rootScope.$on('Addon/OngoingProcess', function(e, name) {
self.setOngoingProcess(name);
});
$scope.$on('$destroy', function() {
disableAddrListener();
disableScannerListener();
@ -70,6 +81,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
disableTabListener();
disableFocusListener();
disableResumeListener();
disableOngoingProcessListener();
$rootScope.hideMenuBar = false;
});
@ -78,23 +90,9 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
$rootScope.$digest();
});
// walletHome
var parseError = function(err) {
if (!err) return;
if (err.message) {
// TODO : this is not used anymore?
if (err.message.indexOf('CORS') >= 0) {
err.message = gettext('Could not connect wallet service. Check your Internet connexion and your wallet service configuration.');
}
if (err.message.indexOf('TIMEDOUT') >= 0) {
err.message = gettext('Wallet service timed out. Check your Internet connexion and your wallet service configuration.');
}
}
};
var accept_msg = gettextCatalog.getString('Accept');
var cancel_msg = gettextCatalog.getString('Cancel');
var confirm_msg = gettextCatalog.getString('Confirm');
$scope.openCopayersModal = function(copayers, copayerId) {
var fc = profileService.focusedClient;
@ -136,13 +134,14 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
});
addressService.getAddress(walletId, false, function(err, addr) {
$scope.gettingAddress = false;
if (!err || addr)
$modalInstance.close(addr);
else {
parseError(err);
if (err) {
self.error = err;
$modalInstance.dismiss('cancel');
return;
}
$modalInstance.close(addr);
});
};
};
@ -168,17 +167,17 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
this.openTxpModal = function(tx, copayers) {
var fc = profileService.focusedClient;
var refreshUntilItChanges = false;
var currentSpendUnconfirmed = $scope.currentSpendUnconfirmed;
var ModalInstanceCtrl = function($scope, $modalInstance) {
$scope.error = null;
$scope.tx = tx;
$scope.amountStr = tx.amountStr;
$scope.feeStr = tx.feeStr;
$scope.alternativeAmountStr = tx.alternativeAmountStr;
$scope.copayers = copayers
$scope.copayerId = fc.credentials.copayerId;
$scope.canSign = fc.canSign();
$scope.loading = null;
$scope.color = fc.backgroundColor;
refreshUntilItChanges = false;
$scope.currentSpendUnconfirmed = currentSpendUnconfirmed;
$scope.getShortNetworkName = function() {
return fc.credentials.networkName.substring(0, 4);
@ -202,7 +201,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
var action = lodash.find(tx.actions, {
copayerId: fc.credentials.copayerId
});
$scope.tx = tx;
$scope.tx = utilService.processTx(tx);
if (!action && tx.status == 'pending')
$scope.tx.pendingForUs = true;
$scope.updateCopayerList();
@ -223,11 +222,14 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
$scope.sign = function(txp) {
var fc = profileService.focusedClient;
if (!fc.canSign())
return;
if (fc.isPrivKeyEncrypted()) {
profileService.unlockFC(function(err) {
if (err) {
parseError(err);
$scope.error = err;
$scope.error = bwsError.msg(err);
return;
}
return $scope.sign(txp);
@ -244,8 +246,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
self.setOngoingProcess();
if (err) {
$scope.loading = false;
parseError(err);
$scope.error = err.message || gettext('Could not accept payment. Check you connection and try again');
$scope.error = bwsError.msg(err, gettextCatalog.getString('Could not accept payment'));
$scope.$digest();
} else {
//if txp has required signatures then broadcast it
@ -257,8 +258,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
self.setOngoingProcess();
$scope.loading = false;
if (err) {
parseError(err);
$scope.error = gettext('Could not broadcast payment. Check you connection and try again');
$scope.error = bwsError.msg(err, gettextCatalog.getString('Could not broadcast payment'));
$scope.$digest();
} else {
$log.debug('Transaction signed and broadcasted')
@ -287,8 +287,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
self.setOngoingProcess();
$scope.loading = false;
if (err) {
parseError(err);
$scope.error = err.message || gettext('Could not reject payment. Check you connection and try again');
$scope.error = bwsError.msg(err, gettextCatalog.getString('Could not reject payment'));
$scope.$digest();
} else {
$modalInstance.close(txpr);
@ -309,8 +308,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
// Hacky: request tries to parse an empty response
if (err && !(err.message && err.message.match(/Unexpected/))) {
parseError(err);
$scope.error = err.message || gettext('Could not delete payment proposal. Check you connection and try again');
$scope.error = bwsError.msg(err, gettextCatalog.getString('Could not delete payment proposal'));
$scope.$digest();
return;
}
@ -328,8 +326,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
self.setOngoingProcess();
$scope.loading = false;
if (err) {
parseError(err);
$scope.error = err.message || gettext('Could not broadcast payment. Check you connection and try again');
$scope.error = bwsError.msg(err, gettextCatalog.getString('Could not broadcast payment'));
$scope.$digest();
} else {
@ -396,13 +393,12 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
self.generatingAddress = false;
if (err) {
parseError(err);
self.addrError = err.message || gettext('Could not create address. Check you connection and try again');
self.addrError = err;
} else {
if (addr)
self.addr[fc.credentials.walletId] = addr;
}
if (addr)
self.addr[fc.credentials.walletId] = addr;
$scope.$digest();
});
});
@ -411,7 +407,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
this.copyAddress = function(addr) {
if (isCordova) {
window.cordova.plugins.clipboard.copy(addr);
window.plugins.toast.showShortCenter('Copied to clipboard');
window.plugins.toast.showShortCenter(gettextCatalog.getString('Copied to clipboard'));
} else if (nodeWebkit.isDefined()) {
nodeWebkit.writeToClipboard(addr);
}
@ -451,6 +447,8 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
$scope.customAlternative = newValue;
if (typeof(newValue) === 'number' && $scope.isRateAvailable) {
$scope.customAmount = parseFloat((rateService.fromFiat(newValue, $scope.alternativeIsoCode) * satToUnit).toFixed($scope.unitDecimals), 10);
} else {
$scope.customAmount = null;
}
},
enumerable: true,
@ -467,7 +465,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
if (typeof(newValue) === 'number' && $scope.isRateAvailable) {
$scope.customAlternative = parseFloat((rateService.toFiat(newValue * $scope.unitToSatoshi, $scope.alternativeIsoCode)).toFixed(2), 10);
} else {
$scope.customAlternative = 0;
$scope.customAlternative = null;
}
$scope.alternativeAmount = $scope.customAlternative;
},
@ -510,7 +508,16 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
});
};
// Send
// Send
var unwatchSpendUnconfirmed = $scope.$watch('currentSpendUnconfirmed', function(newVal, oldVal) {
if (newVal == oldVal) return;
$scope.currentSpendUnconfirmed = newVal;
});
$scope.$on('$destroy', function() {
unwatchSpendUnconfirmed();
});
this.canShowAlternative = function() {
return $scope.showAlternative;
@ -601,6 +608,8 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
$scope.__alternative = newValue;
if (typeof(newValue) === 'number' && self.isRateAvailable) {
$scope._amount = parseFloat((rateService.fromFiat(newValue, self.alternativeIsoCode) * satToUnit).toFixed(self.unitDecimals), 10);
} else {
$scope.__amount = null;
}
},
enumerable: true,
@ -616,7 +625,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
if (typeof(newValue) === 'number' && self.isRateAvailable) {
$scope.__alternative = parseFloat((rateService.toFiat(newValue * self.unitToSatoshi, self.alternativeIsoCode)).toFixed(2), 10);
} else {
$scope.__alternative = 0;
$scope.__alternative = null;
}
self.alternativeAmount = $scope.__alternative;
self.resetError();
@ -640,16 +649,10 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
this.setSendError = function(err) {
var fc = profileService.focusedClient;
$log.warn(err);
parseError(err);
var errMessage =
fc.credentials.m > 1 ? gettext('Could not create payment proposal') : gettext('Could not send payment');
var prefix =
fc.credentials.m > 1 ? gettextCatalog.getString('Could not create payment proposal') : gettextCatalog.getString('Could not send payment');
//This are abnormal situations, but still err message will not be translated
//(the should) we should switch using err.code and use proper gettext messages
errMessage = errMessage + '. ' + (err.message ? err.message : gettext('Check you connection and try again'));
this.error = errMessage;
this.error = bwsError.msg(err, prefix);
$timeout(function() {
$scope.$digest();
@ -676,10 +679,14 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
};
};
this.setFee = function(level) {
this.currentSendFeeLevel = level;
};
this.submitForm = function() {
var fc = profileService.focusedClient;
var unitToSat = this.unitToSatoshi;
if (isCordova && this.isWindowsPhoneApp) {
this.hideAddress = false;
this.hideAmount = false;
@ -708,30 +715,52 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
address = form.address.$modelValue;
amount = parseInt((form.amount.$modelValue * unitToSat).toFixed(0));
fc.sendTxProposal({
toAddress: address,
amount: amount,
message: comment,
payProUrl: paypro ? paypro.url : null,
feePerKb: config.feeValue || 10000,
}, function(err, txp) {
if (err) {
self.setOngoingProcess();
profileService.lockFC();
return self.setSendError(err);
var getFee = function(cb) {
if (form.feePerKb) {
cb(null, form.feePerKb);
} else {
feeService.getCurrentFeeValue(self.currentSendFeeLevel, cb);
}
};
self.signAndBroadcast(txp, function(err) {
self.setOngoingProcess();
profileService.lockFC();
self.resetForm();
getFee(function(err, feePerKb) {
if (err) $log.debug(err);
fc.sendTxProposal({
toAddress: address,
amount: amount,
message: comment,
payProUrl: paypro ? paypro.url : null,
feePerKb: feePerKb,
excludeUnconfirmedUtxos: $scope.currentSpendUnconfirmed ? false : true
}, function(err, txp) {
if (err) {
self.error = err.message ? err.message : gettext('The payment was created but could not be completed. Please try again from home screen');
$scope.$emit('Local/TxProposalAction');
$timeout(function() {
$scope.$digest();
}, 1);
self.setOngoingProcess();
profileService.lockFC();
return self.setSendError(err);
}
if (!fc.canSign()) {
$log.info('No signing proposal: No private key')
self.setOngoingProcess();
self.resetForm();
txStatus.notify(txp, function() {
return $scope.$emit('Local/TxProposalAction');
});
return;
}
self.signAndBroadcast(txp, function(err) {
self.setOngoingProcess();
profileService.lockFC();
self.resetForm();
if (err) {
self.error = err.message ? err.message : gettext('The payment was created but could not be completed. Please try again from home screen');
$scope.$emit('Local/TxProposalAction');
$timeout(function() {
$scope.$digest();
}, 1);
}
});
});
});
}, 100);
@ -745,8 +774,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
profileService.lockFC();
self.setOngoingProcess();
if (err) {
$log.debug('Sign error:', err);
err.message = gettext('The payment was created but could not be signed. Please try again from home screen.') + (err.message ? ' ' + err.message : '');
err.message = bwsError.msg(err, gettextCatalog.getString('The payment was created but could not be signed. Please try again from home screen'));
return cb(err);
}
@ -755,7 +783,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
fc.broadcastTxProposal(signedTx, function(err, btx, memo) {
self.setOngoingProcess();
if (err) {
err.message = gettext('The payment was signed but could not be broadcasted. Please try again from home screen.') + (err.message ? ' ' + err.message : '');
err.message = bwsError.msg(err, gettextCatalog.getString('The payment was signed but could not be broadcasted. Please try again from home screen'));
return cb(err);
}
if (memo)
@ -776,7 +804,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
});
};
this.setForm = function(to, amount, comment) {
this.setForm = function(to, amount, comment, feeRate) {
var form = $scope.sendForm;
if (to) {
form.address.$setViewValue(to);
@ -797,6 +825,10 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
form.comment.$isValid = true;
form.comment.$render();
}
if (feeRate) {
form.feeRate = feeRate;
}
};
@ -807,10 +839,18 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
this.lockAddress = false;
this.lockAmount = false;
this.currentSendFeeLevel = null;
this.hideAdvSend = true;
$scope.currentSpendUnconfirmed = configService.getSync().wallet.spendUnconfirmed;
this._amount = this._address = null;
var form = $scope.sendForm;
if (form && form.feeRate) {
form.feeRate = null;
}
if (form && form.amount) {
form.amount.$pristine = true;
form.amount.$setViewValue('');
@ -944,7 +984,6 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
}
};
// History
function strip(number) {
@ -990,6 +1029,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
};
var modalInstance = $modal.open({
@ -1008,8 +1048,8 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
return actions.hasOwnProperty('create');
};
this._doSendAll = function(amount) {
this.setForm(null, amount);
this._doSendAll = function(amount, feeRate) {
this.setForm(null, amount, null, feeRate);
};
this.confirmDialog = function(msg, cb) {
@ -1024,7 +1064,8 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
} else {
return cb(false);
}
}
},
confirm_msg, [accept_msg, cancel_msg]
);
} else if (isChromeApp) {
// No feedback, alert/confirm not supported.
@ -1034,17 +1075,17 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
}
};
this.sendAll = function(amount, feeStr) {
this.sendAll = function(amount, feeStr, feeRate) {
var self = this;
var msg = gettextCatalog.getString("{{fee}} will be discounted for bitcoin networking fees", {
fee: feeStr
});
this.confirmDialog(msg, function(confirmed){
if (confirmed)
self._doSendAll(amount);
this.confirmDialog(msg, function(confirmed) {
if (confirmed)
self._doSendAll(amount, feeRate);
});
};
};
/* Start setup */

Some files were not shown because too many files have changed in this diff Show More