diff --git a/.codeclimate.yml b/.codeclimate.yml index 3beadbce4a..6dbf8e0cae 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -1,26 +1,50 @@ -# Save as .codeclimate.yml (note leading .) in project root directory -languages: - JavaScript: true - PHP: true +--- +engines: + csslint: + enabled: true + duplication: + enabled: true + config: + languages: + - ruby + - javascript + - python + - php + eslint: + enabled: true + fixme: + enabled: true + phpmd: + enabled: true +ratings: + paths: + - "**.css" + - "**.inc" + - "**.js" + - "**.jsx" + - "**.module" + - "**.php" + - "**.py" + - "**.rb" exclude_paths: -- "gulpfile.js" -- "public/packages/maximebf/php-debugbar/debugbar.js" -- "public/packages/maximebf/php-debugbar/widgets.js" -- "public/packages/maximebf/php-debugbar/openhandler.js" -- "public/packages/maximebf/php-debugbar/widgets/sqlqueries/widget.js" -- "public/js/bootstrap3-typeahead.min.js" -- "public/js/bootstrap-sortable.js" -- "public/js/bootstrap-tagsinput.min.js" -- "public/js/bootstrap-tagsinput.min.js.map" -- "public/js/daterangepicker.js" -- "public/js/jquery-2.1.3.min.js" -- "public/js/jquery-2.1.3.min.js.map" -- "public/js/jquery-ui.min.js" -- "public/js/metisMenu.js" -- "public/js/moment.min.js" -- "public/js/sb-admin-2.js" -- "public/bootstrap/*" -- "resources/lang/*" -- "tests/*" -- "database/*" -- "storage/*" +- gulpfile.js +- public/packages/maximebf/php-debugbar/debugbar.js +- public/packages/maximebf/php-debugbar/widgets.js +- public/packages/maximebf/php-debugbar/openhandler.js +- public/packages/maximebf/php-debugbar/widgets/sqlqueries/widget.js +- public/js/bootstrap3-typeahead.min.js +- public/js/bootstrap-sortable.js +- public/js/bootstrap-tagsinput.min.js +- public/js/bootstrap-tagsinput.min.js.map +- public/js/daterangepicker.js +- public/js/jquery-2.1.3.min.js +- public/js/jquery-2.1.3.min.js.map +- public/js/jquery-ui.min.js +- public/js/metisMenu.js +- public/js/moment.min.js +- public/js/sb-admin-2.js +- public/bootstrap/* +- resources/lang/* +- tests/* +- database/* +- storage/* diff --git a/.csslintrc b/.csslintrc new file mode 100644 index 0000000000..aacba956e5 --- /dev/null +++ b/.csslintrc @@ -0,0 +1,2 @@ +--exclude-exts=.min.css +--ignore=adjoining-classes,box-model,ids,order-alphabetical,unqualified-attributes diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000000..96212a3593 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +**/*{.,-}min.js diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000000..9faa37508e --- /dev/null +++ b/.eslintrc @@ -0,0 +1,213 @@ +ecmaFeatures: + modules: true + jsx: true + +env: + amd: true + browser: true + es6: true + jquery: true + node: true + +# http://eslint.org/docs/rules/ +rules: + # Possible Errors + comma-dangle: [2, never] + no-cond-assign: 2 + no-console: 0 + no-constant-condition: 2 + no-control-regex: 2 + no-debugger: 2 + no-dupe-args: 2 + no-dupe-keys: 2 + no-duplicate-case: 2 + no-empty: 2 + no-empty-character-class: 2 + no-ex-assign: 2 + no-extra-boolean-cast: 2 + no-extra-parens: 0 + no-extra-semi: 2 + no-func-assign: 2 + no-inner-declarations: [2, functions] + no-invalid-regexp: 2 + no-irregular-whitespace: 2 + no-negated-in-lhs: 2 + no-obj-calls: 2 + no-regex-spaces: 2 + no-sparse-arrays: 2 + no-unexpected-multiline: 2 + no-unreachable: 2 + use-isnan: 2 + valid-jsdoc: 0 + valid-typeof: 2 + + # Best Practices + accessor-pairs: 2 + block-scoped-var: 0 + complexity: [2, 6] + consistent-return: 0 + curly: 0 + default-case: 0 + dot-location: 0 + dot-notation: 0 + eqeqeq: 2 + guard-for-in: 2 + no-alert: 2 + no-caller: 2 + no-case-declarations: 2 + no-div-regex: 2 + no-else-return: 0 + no-empty-label: 2 + no-empty-pattern: 2 + no-eq-null: 2 + no-eval: 2 + no-extend-native: 2 + no-extra-bind: 2 + no-fallthrough: 2 + no-floating-decimal: 0 + no-implicit-coercion: 0 + no-implied-eval: 2 + no-invalid-this: 0 + no-iterator: 2 + no-labels: 0 + no-lone-blocks: 2 + no-loop-func: 2 + no-magic-number: 0 + no-multi-spaces: 0 + no-multi-str: 0 + no-native-reassign: 2 + no-new-func: 2 + no-new-wrappers: 2 + no-new: 2 + no-octal-escape: 2 + no-octal: 2 + no-proto: 2 + no-redeclare: 2 + no-return-assign: 2 + no-script-url: 2 + no-self-compare: 2 + no-sequences: 0 + no-throw-literal: 0 + no-unused-expressions: 2 + no-useless-call: 2 + no-useless-concat: 2 + no-void: 2 + no-warning-comments: 0 + no-with: 2 + radix: 2 + vars-on-top: 0 + wrap-iife: 2 + yoda: 0 + + # Strict + strict: 0 + + # Variables + init-declarations: 0 + no-catch-shadow: 2 + no-delete-var: 2 + no-label-var: 2 + no-shadow-restricted-names: 2 + no-shadow: 0 + no-undef-init: 2 + no-undef: 0 + no-undefined: 0 + no-unused-vars: 0 + no-use-before-define: 0 + + # Node.js and CommonJS + callback-return: 2 + global-require: 2 + handle-callback-err: 2 + no-mixed-requires: 0 + no-new-require: 0 + no-path-concat: 2 + no-process-exit: 2 + no-restricted-modules: 0 + no-sync: 0 + + # Stylistic Issues + array-bracket-spacing: 0 + block-spacing: 0 + brace-style: 0 + camelcase: 0 + comma-spacing: 0 + comma-style: 0 + computed-property-spacing: 0 + consistent-this: 0 + eol-last: 0 + func-names: 0 + func-style: 0 + id-length: 0 + id-match: 0 + indent: 0 + jsx-quotes: 0 + key-spacing: 0 + linebreak-style: 0 + lines-around-comment: 0 + max-depth: 0 + max-len: 0 + max-nested-callbacks: 0 + max-params: 0 + max-statements: [2, 30] + new-cap: 0 + new-parens: 0 + newline-after-var: 0 + no-array-constructor: 0 + no-bitwise: 0 + no-continue: 0 + no-inline-comments: 0 + no-lonely-if: 0 + no-mixed-spaces-and-tabs: 0 + no-multiple-empty-lines: 0 + no-negated-condition: 0 + no-nested-ternary: 0 + no-new-object: 0 + no-plusplus: 0 + no-restricted-syntax: 0 + no-spaced-func: 0 + no-ternary: 0 + no-trailing-spaces: 0 + no-underscore-dangle: 0 + no-unneeded-ternary: 0 + object-curly-spacing: 0 + one-var: 0 + operator-assignment: 0 + operator-linebreak: 0 + padded-blocks: 0 + quote-props: 0 + quotes: 0 + require-jsdoc: 0 + semi-spacing: 0 + semi: 0 + sort-vars: 0 + space-after-keywords: 0 + space-before-blocks: 0 + space-before-function-paren: 0 + space-before-keywords: 0 + space-in-parens: 0 + space-infix-ops: 0 + space-return-throw-case: 0 + space-unary-ops: 0 + spaced-comment: 0 + wrap-regex: 0 + + # ECMAScript 6 + arrow-body-style: 0 + arrow-parens: 0 + arrow-spacing: 0 + constructor-super: 0 + generator-star-spacing: 0 + no-arrow-condition: 0 + no-class-assign: 0 + no-const-assign: 0 + no-dupe-class-members: 0 + no-this-before-super: 0 + no-var: 0 + object-shorthand: 0 + prefer-arrow-callback: 0 + prefer-const: 0 + prefer-reflect: 0 + prefer-spread: 0 + prefer-template: 0 + require-yield: 0 diff --git a/.gitignore b/.gitignore index d58cb9cb4e..24a6fb22e5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,17 +1,6 @@ /vendor /node_modules -Homestead.yaml -Homestead.json .env -_ide_helper.php -_ide_helper_models.php -.phpstorm.meta.php storage/ - -# Eclipse project files -.buildpath -.project -.settings/ - .env.local diff --git a/.scrutinizer.yml b/.scrutinizer.yml index 2231b92414..d244d86e35 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -1,3 +1,6 @@ # .scrutinizer.yml tools: external_code_coverage: false +filter: + excluded_paths: + - app/Support/Migration/* diff --git a/.travis.yml b/.travis.yml index abfb2812b8..61763a7648 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,15 @@ language: php sudo: false - - php: - - 5.6 - 7 install: + - phpenv config-rm xdebug.ini - composer selfupdate - - composer install --no-dev - - composer update + - rm composer.lock + - composer update --no-scripts + - php artisan clear-compiled + - php artisan optimize - php artisan env - mv -v .env.testing .env - php artisan env diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..7f915a64c2 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,47 @@ +# Change Log +All notable changes to this project will be documented in this file. +This project adheres to [Semantic Versioning](http://semver.org/). + +## [Unreleased] +- No unreleased changes yet. + +## [3.8.0] - 2016-03-20 +### Added +- Two factor authentication, thanks to the excellent work of [zjean](https://github.com/zjean). +- A new chart showing your net worth in year and multi-year reports. +- You can now see if your current or future rules actually match any transactions, thanks to the excellent work of @roberthorlings. +- New date fields for transactions. They are not used yet in reports or anything, but they can be filled in. +- New routine to export your data. +- Firefly III will mail the site owner when blocked users try to login, or when blocked domains are used in registrations. + + +### Changed +- Firefly III now requires PHP 7.0 minimum. + + +### Fixed +- HTML fixes, thanks to [roberthorlings](https://github.com/roberthorlings) and [zjean](https://github.com/zjean).. +- A bug fix in the ABN Amro importer, thanks to [roberthorlings](https://github.com/roberthorlings) +- It was not possible to change the opening balance, once it had been set. Thanks to [xnyhps](https://github.com/xnyhps) and [marcoveeneman](https://github.com/marcoveeneman) for spotting this. +- Various other bug fixes. + + + +## [3.4.2] - 2015-05-25 +### Added +- Initial release. + +### Changed +- Initial release. + +### Deprecated +- Initial release. + +### Removed +- Initial release. + +### Fixed +- Initial release. + +### Security +- Initial release. diff --git a/README.md b/README.md index 43bdb2df8d..7c92d457f4 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,11 @@ # Firefly III +[![Requires PHP7](https://img.shields.io/badge/php-7.0-red.svg)](https://secure.php.net/downloads.php#v7.0.4) [![Latest Stable Version](https://poser.pugx.org/grumpydictator/firefly-iii/v/stable)](https://packagist.org/packages/grumpydictator/firefly-iii) -[![Total Downloads](https://poser.pugx.org/grumpydictator/firefly-iii/downloads)](https://packagist.org/packages/grumpydictator/firefly-iii) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/JC5/firefly-iii/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/JC5/firefly-iii/?branch=master) [![Build Status](https://scrutinizer-ci.com/g/JC5/firefly-iii/badges/build.png?b=master)](https://scrutinizer-ci.com/g/JC5/firefly-iii/build-status/master) [![SensioLabsInsight](https://insight.sensiolabs.com/projects/d44c7012-5f50-41ad-add8-8445330e4102/mini.png)](https://insight.sensiolabs.com/projects/d44c7012-5f50-41ad-add8-8445330e4102) [![Code Climate](https://codeclimate.com/github/JC5/firefly-iii/badges/gpa.svg)](https://codeclimate.com/github/JC5/firefly-iii) -[![Project Status](http://stillmaintained.com/JC5/firefly-iii.png?a=b)](http://stillmaintained.com/JC5/firefly-iii) ## About diff --git a/app/Console/Commands/UpgradeFireflyInstructions.php b/app/Console/Commands/UpgradeFireflyInstructions.php index bb99309c05..b15d3c4936 100644 --- a/app/Console/Commands/UpgradeFireflyInstructions.php +++ b/app/Console/Commands/UpgradeFireflyInstructions.php @@ -1,4 +1,5 @@ line('+------------------------------------------------------------------------------+'); $this->line(''); diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 88960c8a36..7ce107879b 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -1,4 +1,6 @@ journal = $journal; diff --git a/app/Events/TransactionJournalUpdated.php b/app/Events/TransactionJournalUpdated.php index 0ea23204e3..edb9a82a12 100644 --- a/app/Events/TransactionJournalUpdated.php +++ b/app/Events/TransactionJournalUpdated.php @@ -1,4 +1,7 @@ -view('errors.FireflyException', ['exception' => $exception, 'debug' => $isDebug], 500); + } + return parent::render($request, $exception); } + /** * Report or log an exception. * @@ -51,6 +64,26 @@ class Handler extends ExceptionHandler */ public function report(Exception $exception) { + + if ($exception instanceof FireflyException || $exception instanceof ErrorException) { + + $user = Auth::check() ? Auth::user() : new User; + + $data = [ + 'class' => get_class($exception), + 'errorMessage' => $exception->getMessage(), + 'time' => date('r'), + 'stackTrace' => $exception->getTraceAsString(), + 'file' => $exception->getFile(), + 'line' => $exception->getLine(), + 'code' => $exception->getCode(), + ]; + + // create job that will mail. + $job = new MailError($user, env('SITE_OWNER'), Request::ip(), $data); + dispatch($job); + } + parent::report($exception); } } diff --git a/app/Exceptions/NotImplementedException.php b/app/Exceptions/NotImplementedException.php index c1f3ed4500..47c43b9e68 100644 --- a/app/Exceptions/NotImplementedException.php +++ b/app/Exceptions/NotImplementedException.php @@ -1,4 +1,5 @@ repository = app('FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface'); + // make storage: + $this->uploadDisk = Storage::disk('upload'); + $this->exportDisk = Storage::disk('export'); + + parent::__construct($job); + } + + /** + * + */ + public function run() + { + // grab all the users attachments: + $attachments = $this->getAttachments(); + + /** @var Attachment $attachment */ + foreach ($attachments as $attachment) { + $this->exportAttachment($attachment); + } + + // put the explanation string in a file and attach it as well. + $file = $this->job->key . '-Source of all your attachments explained.txt'; + $this->exportDisk->put($file, $this->explanationString); + Log::debug('Also put explanation file "' . $file . '" in the zip.'); + $this->getFiles()->push($file); + } + + /** + * @param Attachment $attachment + */ + private function explain(Attachment $attachment) + { + /** @var TransactionJournal $journal */ + $journal = $attachment->attachable; + $args = [ + 'attachment_name' => $attachment->filename, + 'attachment_id' => $attachment->id, + 'type' => strtolower($journal->transactionType->type), + 'description' => $journal->description, + 'journal_id' => $journal->id, + 'date' => $journal->date->formatLocalized(strval(trans('config.month_and_day'))), + 'amount' => Amount::formatJournal($journal, false), + ]; + $string = trans('firefly.attachment_explanation', $args) . "\n"; + $this->explanationString .= $string; + + } + + /** + * @param Attachment $attachment + * + * @return bool + */ + private function exportAttachment(Attachment $attachment): bool + { + $file = $attachment->fileName(); + Log::debug('Original file is at "' . $file . '".'); + if ($this->uploadDisk->exists($file)) { + try { + $decrypted = Crypt::decrypt($this->uploadDisk->get($file)); + $exportFile = $this->exportFileName($attachment); + $this->exportDisk->put($exportFile, $decrypted); + $this->getFiles()->push($exportFile); + Log::debug('Stored file content in new file "' . $exportFile . '", which will be in the final zip file.'); + + // explain: + $this->explain($attachment); + } catch (DecryptException $e) { + Log::error('Catchable error: could not decrypt attachment #' . $attachment->id . ' because: ' . $e->getMessage()); + } + + } + + return true; + } + + /** + * Returns the new file name for the export file. + * + * @param $attachment + * + * @return string + */ + private function exportFileName($attachment): string + { + + return sprintf('%s-Attachment nr. %s - %s', $this->job->key, strval($attachment->id), $attachment->filename); + } + + /** + * @return Collection + */ + private function getAttachments(): Collection + { + $attachments = $this->repository->get(); + + Log::debug('Found ' . $attachments->count() . ' attachments.'); + + return $attachments; + } +} diff --git a/app/Export/Collector/BasicCollector.php b/app/Export/Collector/BasicCollector.php new file mode 100644 index 0000000000..c779a1fa02 --- /dev/null +++ b/app/Export/Collector/BasicCollector.php @@ -0,0 +1,57 @@ +files = new Collection; + $this->job = $job; + } + + /** + * @return Collection + */ + public function getFiles() + { + return $this->files; + } + + /** + * @param Collection $files + */ + public function setFiles(Collection $files) + { + $this->files = $files; + } + + +} diff --git a/app/Export/Collector/CollectorInterface.php b/app/Export/Collector/CollectorInterface.php new file mode 100644 index 0000000000..f220c479ec --- /dev/null +++ b/app/Export/Collector/CollectorInterface.php @@ -0,0 +1,38 @@ +uploadDisk = Storage::disk('upload'); + $this->exportDisk = Storage::disk('export'); + $this->expected = 'csv-upload-' . Auth::user()->id . '-'; + } + + /** + * + */ + public function run() + { + // grab upload directory. + $files = $this->uploadDisk->files(); + Log::debug('Found ' . count($files) . ' files in the upload directory.'); + + foreach ($files as $entry) { + $this->processOldUpload($entry); + } + } + + /** + * @param string $entry + * + * @return string + */ + private function getOriginalUploadDate(string $entry): string + { + // this is an original upload. + $parts = explode('-', str_replace(['.csv.encrypted', $this->expected], '', $entry)); + $originalUpload = intval($parts[1]); + $date = date('Y-m-d \a\t H-i-s', $originalUpload); + + return $date; + } + + /** + * @param string $entry + * + * @return bool + */ + private function isValidFile(string $entry): bool + { + $len = strlen($this->expected); + if (substr($entry, 0, $len) === $this->expected) { + Log::debug($entry . ' is part of this users original uploads.'); + + return true; + } + Log::debug($entry . ' is not part of this users original uploads.'); + + return false; + } + + /** + * @param $entry + */ + private function processOldUpload(string $entry) + { + $content = ''; + + if ($this->isValidFile($entry)) { + try { + $content = Crypt::decrypt($this->uploadDisk->get($entry)); + } catch (DecryptException $e) { + Log::error('Could not decrypt old CSV import file ' . $entry . '. Skipped because ' . $e->getMessage()); + } + } + if (strlen($content) > 0) { + // continue with file: + $date = $this->getOriginalUploadDate($entry); + $file = $this->job->key . '-Old CSV import dated ' . $date . '.csv'; + Log::debug('Will put "' . $file . '" in the zip file.'); + $this->exportDisk->put($file, $content); + $this->getFiles()->push($file); + } + } +} diff --git a/app/Export/ConfigurationFile.php b/app/Export/ConfigurationFile.php new file mode 100644 index 0000000000..c78e6501b7 --- /dev/null +++ b/app/Export/ConfigurationFile.php @@ -0,0 +1,67 @@ +job = $job; + $this->exportDisk = Storage::disk('export'); + } + + /** + * @return bool + */ + public function make() + { + $fields = array_keys(get_class_vars(Entry::class)); + $types = Entry::getTypes(); + + $configuration = [ + 'date-format' => 'Y-m-d', // unfortunately, this is hard-coded. + 'has-headers' => true, + 'map' => [], // we could build a map if necessary for easy re-import. + 'roles' => [], + 'mapped' => [], + 'specifix' => [], + ]; + foreach ($fields as $field) { + $configuration['roles'][] = $types[$field]; + } + $file = $this->job->key . '-configuration.json'; + Log::debug('Created JSON config file.'); + Log::debug('Will put "' . $file . '" in the ZIP file.'); + $this->exportDisk->put($file, json_encode($configuration, JSON_PRETTY_PRINT)); + + return $file; + } + +} diff --git a/app/Export/Entry.php b/app/Export/Entry.php new file mode 100644 index 0000000000..3580cc6960 --- /dev/null +++ b/app/Export/Entry.php @@ -0,0 +1,460 @@ +setDescription($journal->description); + $entry->setDate($journal->date->format('Y-m-d')); + $entry->setAmount(TransactionJournal::amount($journal)); + + /** @var Budget $budget */ + $budget = $journal->budgets->first(); + if (!is_null($budget)) { + $entry->setBudgetId($budget->id); + $entry->setBudgetName($budget->name); + } + + /** @var Category $category */ + $category = $journal->categories->first(); + if (!is_null($category)) { + $entry->setCategoryId($category->id); + $entry->setCategoryName($category->name); + } + + if (!is_null($journal->bill_id)) { + $entry->setBillId($journal->bill_id); + $entry->setBillName($journal->bill->name); + } + + /** @var Account $sourceAccount */ + $sourceAccount = TransactionJournal::sourceAccount($journal); + $entry->setFromAccountId($sourceAccount->id); + $entry->setFromAccountName($sourceAccount->name); + $entry->setFromAccountIban($sourceAccount->iban); + $entry->setFromAccountType($sourceAccount->accountType->type); + $entry->setFromAccountNumber($sourceAccount->getMeta('accountNumber')); + + + /** @var Account $destination */ + $destination = TransactionJournal::destinationAccount($journal); + $entry->setToAccountId($destination->id); + $entry->setToAccountName($destination->name); + $entry->setToAccountIban($destination->iban); + $entry->setToAccountType($destination->accountType->type); + $entry->setToAccountNumber($destination->getMeta('accountNumber')); + + return $entry; + + } + + /** + * @return array + */ + public static function getTypes(): array + { + // key = field name (see top of class) + // value = field type (see csv.php under 'roles') + return [ + 'amount' => 'amount', + 'date' => 'date-transaction', + 'description' => 'description', + 'billId' => 'bill-id', + 'billName' => 'bill-name', + 'budgetId' => 'budget-id', + 'budgetName' => 'budget-name', + 'categoryId' => 'category-id', + 'categoryName' => 'category-name', + 'fromAccountId' => 'account-id', + 'fromAccountName' => 'account-name', + 'fromAccountIban' => 'account-iban', + 'fromAccountType' => '_ignore', // no, Firefly cannot import what it exports. I know :D + 'toAccountId' => 'opposing-id', + 'toAccountName' => 'opposing-name', + 'toAccountIban' => 'opposing-iban', + 'toAccountType' => '_ignore', + ]; + } + + /** + * @return string + */ + public function getAmount(): string + { + return $this->amount; + } + + /** + * @param string $amount + */ + public function setAmount(string $amount) + { + $this->amount = $amount; + } + + /** + * @return int + */ + public function getBillId() + { + return $this->billId; + } + + /** + * @param int $billId + */ + public function setBillId($billId) + { + $this->billId = $billId; + } + + /** + * @return string + */ + public function getBillName() + { + return $this->billName; + } + + /** + * @param string $billName + */ + public function setBillName($billName) + { + $this->billName = $billName; + } + + /** + * @return int + */ + public function getBudgetId() + { + return $this->budgetId; + } + + /** + * @param int $budgetId + */ + public function setBudgetId($budgetId) + { + $this->budgetId = $budgetId; + } + + /** + * @return string + */ + public function getBudgetName() + { + return $this->budgetName; + } + + /** + * @param string $budgetName + */ + public function setBudgetName($budgetName) + { + $this->budgetName = $budgetName; + } + + /** + * @return int + */ + public function getCategoryId() + { + return $this->categoryId; + } + + /** + * @param int $categoryId + */ + public function setCategoryId($categoryId) + { + $this->categoryId = $categoryId; + } + + /** + * @return string + */ + public function getCategoryName() + { + return $this->categoryName; + } + + /** + * @param string $categoryName + */ + public function setCategoryName($categoryName) + { + $this->categoryName = $categoryName; + } + + /** + * @return string + */ + public function getDate() + { + return $this->date; + } + + /** + * @param string $date + */ + public function setDate(string $date) + { + $this->date = $date; + } + + /** + * @return string + */ + public function getDescription() + { + return $this->description; + } + + /** + * @param string $description + */ + public function setDescription(string $description) + { + $this->description = $description; + } + + /** + * @return string + */ + public function getFromAccountIban() + { + return $this->fromAccountIban; + } + + /** + * @param string $fromAccountIban + */ + public function setFromAccountIban($fromAccountIban) + { + $this->fromAccountIban = $fromAccountIban; + } + + /** + * @return int + */ + public function getFromAccountId() + { + return $this->fromAccountId; + } + + /** + * @param int $fromAccountId + */ + public function setFromAccountId($fromAccountId) + { + $this->fromAccountId = $fromAccountId; + } + + /** + * @return string + */ + public function getFromAccountName() + { + return $this->fromAccountName; + } + + /** + * @param string $fromAccountName + */ + public function setFromAccountName($fromAccountName) + { + $this->fromAccountName = $fromAccountName; + } + + /** + * @return mixed + */ + public function getFromAccountNumber() + { + return $this->fromAccountNumber; + } + + /** + * @param mixed $fromAccountNumber + */ + public function setFromAccountNumber($fromAccountNumber) + { + $this->fromAccountNumber = $fromAccountNumber; + } + + /** + * @return string + */ + public function getFromAccountType() + { + return $this->fromAccountType; + } + + /** + * @param string $fromAccountType + */ + public function setFromAccountType($fromAccountType) + { + $this->fromAccountType = $fromAccountType; + } + + /** + * @return string + */ + public function getToAccountIban() + { + return $this->toAccountIban; + } + + /** + * @param string $toAccountIban + */ + public function setToAccountIban($toAccountIban) + { + $this->toAccountIban = $toAccountIban; + } + + /** + * @return int + */ + public function getToAccountId() + { + return $this->toAccountId; + } + + /** + * @param int $toAccountId + */ + public function setToAccountId($toAccountId) + { + $this->toAccountId = $toAccountId; + } + + /** + * @return string + */ + public function getToAccountName() + { + return $this->toAccountName; + } + + /** + * @param string $toAccountName + */ + public function setToAccountName($toAccountName) + { + $this->toAccountName = $toAccountName; + } + + /** + * @return mixed + */ + public function getToAccountNumber() + { + return $this->toAccountNumber; + } + + /** + * @param mixed $toAccountNumber + */ + public function setToAccountNumber($toAccountNumber) + { + $this->toAccountNumber = $toAccountNumber; + } + + /** + * @return string + */ + public function getToAccountType() + { + return $this->toAccountType; + } + + /** + * @param string $toAccountType + */ + public function setToAccountType($toAccountType) + { + $this->toAccountType = $toAccountType; + } + + +} diff --git a/app/Export/Exporter/BasicExporter.php b/app/Export/Exporter/BasicExporter.php new file mode 100644 index 0000000000..04f2002724 --- /dev/null +++ b/app/Export/Exporter/BasicExporter.php @@ -0,0 +1,56 @@ +entries = new Collection; + $this->job = $job; + } + + /** + * @return Collection + */ + public function getEntries() + { + return $this->entries; + } + + /** + * @param Collection $entries + */ + public function setEntries(Collection $entries) + { + $this->entries = $entries; + } + + +} diff --git a/app/Export/Exporter/CsvExporter.php b/app/Export/Exporter/CsvExporter.php new file mode 100644 index 0000000000..6799ea591c --- /dev/null +++ b/app/Export/Exporter/CsvExporter.php @@ -0,0 +1,81 @@ +fileName; + } + + /** + * + */ + public function run() + { + // create temporary file: + $this->tempFile(); + + // necessary for CSV writer: + $fullPath = storage_path('export') . DIRECTORY_SEPARATOR . $this->fileName; + + // create CSV writer: + $writer = Writer::createFromPath(new SplFileObject($fullPath, 'a+'), 'w'); + + // all rows: + $rows = []; + + // add header: + $first = $this->getEntries()->first(); + $rows[] = array_keys(get_object_vars($first)); + + // then the rest: + /** @var Entry $entry */ + foreach ($this->getEntries() as $entry) { + $rows[] = array_values(get_object_vars($entry)); + + } + $writer->insertAll($rows); + } + + private function tempFile() + { + $this->fileName = $this->job->key . '-records.csv'; + } +} diff --git a/app/Export/Exporter/ExporterInterface.php b/app/Export/Exporter/ExporterInterface.php new file mode 100644 index 0000000000..aed29b2daa --- /dev/null +++ b/app/Export/Exporter/ExporterInterface.php @@ -0,0 +1,43 @@ +settings = $settings; + $this->accounts = $settings['accounts']; + $this->exportFormat = $settings['exportFormat']; + $this->includeAttachments = $settings['includeAttachments']; + $this->includeConfig = $settings['includeConfig']; + $this->includeOldUploads = $settings['includeOldUploads']; + $this->job = $settings['job']; + $this->journals = new Collection; + $this->exportEntries = new Collection; + $this->files = new Collection; + + } + + /** + * + */ + public function collectAttachments() + { + $attachmentCollector = app('FireflyIII\Export\Collector\AttachmentCollector', [$this->job]); + $attachmentCollector->run(); + $this->files = $this->files->merge($attachmentCollector->getFiles()); + } + + /** + * + */ + public function collectJournals() + { + $args = [$this->accounts, Auth::user(), $this->settings['startDate'], $this->settings['endDate']]; + $journalCollector = app('FireflyIII\Repositories\Journal\JournalCollector', $args); + $this->journals = $journalCollector->collect(); + Log::debug( + 'Collected ' . + $this->journals->count() . ' journals (between ' . + $this->settings['startDate']->format('Y-m-d') . ' and ' . + $this->settings['endDate']->format('Y-m-d') + . ').' + ); + } + + public function collectOldUploads() + { + $uploadCollector = app('FireflyIII\Export\Collector\UploadCollector', [$this->job]); + $uploadCollector->run(); + + $this->files = $this->files->merge($uploadCollector->getFiles()); + } + + /** + * + */ + public function convertJournals() + { + $count = 0; + /** @var TransactionJournal $journal */ + foreach ($this->journals as $journal) { + $this->exportEntries->push(Entry::fromJournal($journal)); + $count++; + } + Log::debug('Converted ' . $count . ' journals to "Entry" objects.'); + } + + public function createConfigFile() + { + $this->configurationMaker = app('FireflyIII\Export\ConfigurationFile', [$this->job]); + $this->files->push($this->configurationMaker->make()); + } + + public function createZipFile() + { + $zip = new ZipArchive; + $file = $this->job->key . '.zip'; + $fullPath = storage_path('export') . '/' . $file; + Log::debug('Will create zip file at ' . $fullPath); + + if ($zip->open($fullPath, ZipArchive::CREATE) !== true) { + throw new FireflyException('Cannot store zip file.'); + } + // for each file in the collection, add it to the zip file. + $disk = Storage::disk('export'); + foreach ($this->getFiles() as $entry) { + // is part of this job? + $zipFileName = str_replace($this->job->key . '-', '', $entry); + $result = $zip->addFromString($zipFileName, $disk->get($entry)); + if (!$result) { + Log::error('Could not add "' . $entry . '" into zip file as "' . $zipFileName . '".'); + } + } + + $zip->close(); + + // delete the files: + foreach ($this->getFiles() as $file) { + Log::debug('Will now delete file "' . $file . '".'); + $disk->delete($file); + } + Log::debug('Done!'); + } + + /** + * + */ + public function exportJournals() + { + $exporterClass = Config::get('firefly.export_formats.' . $this->exportFormat); + $exporter = app($exporterClass, [$this->job]); + Log::debug('Going to export ' . $this->exportEntries->count() . ' export entries into ' . $this->exportFormat . ' format.'); + $exporter->setEntries($this->exportEntries); + $exporter->run(); + $this->files->push($exporter->getFileName()); + Log::debug('Added "' . $exporter->getFileName() . '" to the list of files to include in the zip.'); + } + + /** + * @return Collection + */ + public function getFiles() + { + return $this->files; + } +} diff --git a/app/Generator/Chart/Account/AccountChartGeneratorInterface.php b/app/Generator/Chart/Account/AccountChartGeneratorInterface.php index 0e09e5e077..f4e5ba6938 100644 --- a/app/Generator/Chart/Account/AccountChartGeneratorInterface.php +++ b/app/Generator/Chart/Account/AccountChartGeneratorInterface.php @@ -1,4 +1,5 @@ 1, @@ -30,7 +30,6 @@ class ChartJsAccountChartGenerator implements AccountChartGeneratorInterface 'label' => trans('firefly.spent'), 'data' => []]]]; - bcscale(2); $start->subDay(); $ids = $this->getIdsFromCollection($accounts); $startBalances = Steam::balancesById($ids, $start); @@ -69,7 +68,7 @@ class ChartJsAccountChartGenerator implements AccountChartGeneratorInterface * * @return array */ - public function frontpage(Collection $accounts, Carbon $start, Carbon $end) + public function frontpage(Collection $accounts, Carbon $start, Carbon $end): array { // language: $format = (string)trans('config.month_and_day'); @@ -116,7 +115,7 @@ class ChartJsAccountChartGenerator implements AccountChartGeneratorInterface * * @return array */ - public function single(Account $account, Carbon $start, Carbon $end) + public function single(Account $account, Carbon $start, Carbon $end): array { // language: $format = (string)trans('config.month_and_day'); @@ -137,7 +136,7 @@ class ChartJsAccountChartGenerator implements AccountChartGeneratorInterface while ($end >= $current) { $theDate = $current->format('Y-m-d'); - $balance = isset($range[$theDate]) ? $range[$theDate] : $previous; + $balance = $range[$theDate] ?? $previous; $data['labels'][] = $current->formatLocalized($format); $data['datasets'][0]['data'][] = $balance; @@ -153,7 +152,7 @@ class ChartJsAccountChartGenerator implements AccountChartGeneratorInterface * * @return array */ - protected function getIdsFromCollection(Collection $collection) + protected function getIdsFromCollection(Collection $collection): array { $ids = []; foreach ($collection as $entry) { @@ -170,7 +169,7 @@ class ChartJsAccountChartGenerator implements AccountChartGeneratorInterface * * @return string */ - protected function isInArray($array, $entryId) + protected function isInArray($array, $entryId): string { if (isset($array[$entryId])) { return $array[$entryId]; diff --git a/app/Generator/Chart/Bill/BillChartGeneratorInterface.php b/app/Generator/Chart/Bill/BillChartGeneratorInterface.php index 077443ed94..1baa03cc3e 100644 --- a/app/Generator/Chart/Bill/BillChartGeneratorInterface.php +++ b/app/Generator/Chart/Bill/BillChartGeneratorInterface.php @@ -1,4 +1,5 @@ round($unpaid, 2), @@ -38,7 +38,7 @@ class ChartJsBillChartGenerator implements BillChartGeneratorInterface 'label' => trans('firefly.unpaid'), ], [ - 'value' => round($paid * -1, 2), // paid is negative, must be positive. + 'value' => round(bcmul($paid, '-1'), 2), // paid is negative, must be positive. 'color' => 'rgba(0, 141, 76, 0.7)', 'highlight' => 'rgba(0, 141, 76, 0.9)', 'label' => trans('firefly.paid'), @@ -54,7 +54,7 @@ class ChartJsBillChartGenerator implements BillChartGeneratorInterface * * @return array */ - public function single(Bill $bill, Collection $entries) + public function single(Bill $bill, Collection $entries): array { $format = (string)trans('config.month'); $data = [ @@ -73,7 +73,7 @@ class ChartJsBillChartGenerator implements BillChartGeneratorInterface /* * journalAmount has been collected in BillRepository::getJournals */ - $actualAmount[] = round(($entry->journalAmount * -1), 2); + $actualAmount[] = round(TransactionJournal::amountPositive($entry), 2); } $data['datasets'][] = [ diff --git a/app/Generator/Chart/Budget/BudgetChartGeneratorInterface.php b/app/Generator/Chart/Budget/BudgetChartGeneratorInterface.php index dbe988f585..fe85f83a70 100644 --- a/app/Generator/Chart/Budget/BudgetChartGeneratorInterface.php +++ b/app/Generator/Chart/Budget/BudgetChartGeneratorInterface.php @@ -1,4 +1,5 @@ data; @@ -56,7 +56,7 @@ class ChartJsBudgetChartGenerator implements BudgetChartGeneratorInterface * * @return array */ - public function budgetLimit(Collection $entries) + public function budgetLimit(Collection $entries): array { return $this->budget($entries, 'monthAndDay'); } @@ -66,7 +66,7 @@ class ChartJsBudgetChartGenerator implements BudgetChartGeneratorInterface * * @return array */ - public function frontpage(Collection $entries) + public function frontpage(Collection $entries): array { $data = [ 'count' => 0, @@ -84,8 +84,8 @@ class ChartJsBudgetChartGenerator implements BudgetChartGeneratorInterface foreach ($filtered as $entry) { $data['labels'][] = $entry[0]; $left[] = round($entry[1], 2); - $spent[] = round($entry[2] * -1, 2); // spent is coming in negative, must be positive - $overspent[] = round($entry[3] * -1, 2); // same + $spent[] = round(bcmul($entry[2], '-1'), 2); // spent is coming in negative, must be positive + $overspent[] = round(bcmul($entry[3], '-1'), 2); // same } $data['datasets'][] = [ @@ -111,7 +111,7 @@ class ChartJsBudgetChartGenerator implements BudgetChartGeneratorInterface * * @return array */ - public function multiYear(Collection $entries) + public function multiYear(Collection $entries): array { // dataset: $data = [ @@ -146,7 +146,7 @@ class ChartJsBudgetChartGenerator implements BudgetChartGeneratorInterface * * @return array */ - public function year(Collection $budgets, Collection $entries) + public function year(Collection $budgets, Collection $entries): array { // language: $format = (string)trans('config.month'); diff --git a/app/Generator/Chart/Category/CategoryChartGeneratorInterface.php b/app/Generator/Chart/Category/CategoryChartGeneratorInterface.php index 7357ab3225..c5d0bca4bb 100644 --- a/app/Generator/Chart/Category/CategoryChartGeneratorInterface.php +++ b/app/Generator/Chart/Category/CategoryChartGeneratorInterface.php @@ -1,4 +1,5 @@ 1, @@ -102,7 +102,7 @@ class ChartJsCategoryChartGenerator implements CategoryChartGeneratorInterface foreach ($entries as $entry) { if ($entry->spent != 0) { $data['labels'][] = $entry->name; - $data['datasets'][0]['data'][] = round(($entry->spent * -1), 2); + $data['datasets'][0]['data'][] = round(bcmul($entry->spent, '-1'), 2); } } @@ -114,7 +114,7 @@ class ChartJsCategoryChartGenerator implements CategoryChartGeneratorInterface * * @return array */ - public function multiYear(Collection $entries) + public function multiYear(Collection $entries): array { // dataset: $data = [ @@ -154,7 +154,7 @@ class ChartJsCategoryChartGenerator implements CategoryChartGeneratorInterface * * @return array */ - public function period(Collection $entries) + public function period(Collection $entries): array { return $this->all($entries); @@ -166,7 +166,7 @@ class ChartJsCategoryChartGenerator implements CategoryChartGeneratorInterface * * @return array */ - public function spentInPeriod(Collection $categories, Collection $entries) + public function spentInPeriod(Collection $categories, Collection $entries): array { // language: diff --git a/app/Generator/Chart/PiggyBank/ChartJsPiggyBankChartGenerator.php b/app/Generator/Chart/PiggyBank/ChartJsPiggyBankChartGenerator.php index 1f737573a3..086e208039 100644 --- a/app/Generator/Chart/PiggyBank/ChartJsPiggyBankChartGenerator.php +++ b/app/Generator/Chart/PiggyBank/ChartJsPiggyBankChartGenerator.php @@ -1,5 +1,5 @@ date); $sum = bcadd($sum, $entry->sum); diff --git a/app/Generator/Chart/PiggyBank/PiggyBankChartGeneratorInterface.php b/app/Generator/Chart/PiggyBank/PiggyBankChartGeneratorInterface.php index a45eace0e6..336bbceb71 100644 --- a/app/Generator/Chart/PiggyBank/PiggyBankChartGeneratorInterface.php +++ b/app/Generator/Chart/PiggyBank/PiggyBankChartGeneratorInterface.php @@ -1,4 +1,5 @@ 2, @@ -52,7 +52,7 @@ class ChartJsReportChartGenerator implements ReportChartGeneratorInterface * * @return array */ - public function multiYearInOutSummarized($income, $expense, $count) + public function multiYearInOutSummarized(string $income, string $expense, int $count): array { $data = [ 'count' => 2, @@ -81,7 +81,33 @@ class ChartJsReportChartGenerator implements ReportChartGeneratorInterface * * @return array */ - public function yearInOut(Collection $entries) + public function netWorth(Collection $entries) : array + { + $format = (string)trans('config.month_and_day'); + $data = [ + 'count' => 1, + 'labels' => [], + 'datasets' => [ + [ + 'label' => trans('firefly.net-worth'), + 'data' => [], + ], + ], + ]; + foreach ($entries as $entry) { + $data['labels'][] = trim($entry['date']->formatLocalized($format)); + $data['datasets'][0]['data'][] = round($entry['net-worth'], 2); + } + + return $data; + } + + /** + * @param Collection $entries + * + * @return array + */ + public function yearInOut(Collection $entries): array { // language: $format = (string)trans('config.month'); @@ -117,7 +143,7 @@ class ChartJsReportChartGenerator implements ReportChartGeneratorInterface * * @return array */ - public function yearInOutSummarized($income, $expense, $count) + public function yearInOutSummarized(string $income, string $expense, int $count): array { $data = [ diff --git a/app/Generator/Chart/Report/ReportChartGeneratorInterface.php b/app/Generator/Chart/Report/ReportChartGeneratorInterface.php index 8b5f753232..c1999137dc 100644 --- a/app/Generator/Chart/Report/ReportChartGeneratorInterface.php +++ b/app/Generator/Chart/Report/ReportChartGeneratorInterface.php @@ -1,4 +1,5 @@ journal; @@ -49,12 +41,11 @@ class ConnectJournalToPiggyBank if (is_null($repetition)) { return true; } - bcscale(2); - $amount = $journal->amount_positive; + $amount = TransactionJournal::amountPositive($journal); // if piggy account matches source account, the amount is positive - if ($piggyBank->account_id == $journal->source_account->id) { - $amount = $amount * -1; + if ($piggyBank->account_id == TransactionJournal::sourceAccount($journal)->id) { + $amount = bcmul($amount, '-1'); } diff --git a/app/Handlers/Events/FireRulesForStore.php b/app/Handlers/Events/FireRulesForStore.php index 0c3a67bc46..38e37bc64a 100644 --- a/app/Handlers/Events/FireRulesForStore.php +++ b/app/Handlers/Events/FireRulesForStore.php @@ -1,4 +1,5 @@ get(['rules.*']); /** @var Rule $rule */ foreach ($rules as $rule) { - Log::debug('Now handling rule #' . $rule->id . ' (' . $rule->title . ')'); - $processor = new Processor($rule, $event->journal); - // get some return out of this? - $processor->handle(); + Log::debug('Now handling rule #' . $rule->id . ' (' . $rule->title . ')'); + $processor = Processor::make($rule); + $processor->handleTransactionJournal($event->journal); if ($rule->stop_processing) { - break; + return true; } } } + + return true; } } diff --git a/app/Handlers/Events/FireRulesForUpdate.php b/app/Handlers/Events/FireRulesForUpdate.php index e829ee16b8..a645f151ff 100644 --- a/app/Handlers/Events/FireRulesForUpdate.php +++ b/app/Handlers/Events/FireRulesForUpdate.php @@ -1,4 +1,5 @@ id . ' (' . $rule->title . ')'); - $processor = new Processor($rule, $event->journal); - // get some return out of this? - $processor->handle(); + Log::debug('Now handling rule #' . $rule->id . ' (' . $rule->title . ')'); + $processor = Processor::make($rule); + $processor->handleTransactionJournal($event->journal); if ($rule->stop_processing) { break; @@ -70,5 +62,7 @@ class FireRulesForUpdate } } + + return true; } } diff --git a/app/Handlers/Events/ScanForBillsAfterStore.php b/app/Handlers/Events/ScanForBillsAfterStore.php index 81fa3f870f..ffcb3f26ac 100644 --- a/app/Handlers/Events/ScanForBillsAfterStore.php +++ b/app/Handlers/Events/ScanForBillsAfterStore.php @@ -1,4 +1,5 @@ journal; BillScanner::scan($journal); + + return true; } } diff --git a/app/Handlers/Events/ScanForBillsAfterUpdate.php b/app/Handlers/Events/ScanForBillsAfterUpdate.php index c17a79360a..5061b9e315 100644 --- a/app/Handlers/Events/ScanForBillsAfterUpdate.php +++ b/app/Handlers/Events/ScanForBillsAfterUpdate.php @@ -1,4 +1,5 @@ journal; BillScanner::scan($journal); + + return true; } } diff --git a/app/Handlers/Events/UpdateJournalConnection.php b/app/Handlers/Events/UpdateJournalConnection.php index e04b44f088..0a5e5f2804 100644 --- a/app/Handlers/Events/UpdateJournalConnection.php +++ b/app/Handlers/Events/UpdateJournalConnection.php @@ -1,8 +1,11 @@ -journal; @@ -37,7 +31,7 @@ class UpdateJournalConnection /** @var PiggyBankEvent $event */ $event = PiggyBankEvent::where('transaction_journal_id', $journal->id)->first(); if (is_null($event)) { - return; + return false; } $piggyBank = $event->piggyBank()->first(); $repetition = null; @@ -47,11 +41,10 @@ class UpdateJournalConnection } if (is_null($repetition)) { - return; + return false; } - bcscale(2); - $amount = $journal->amount; + $amount = TransactionJournal::amount($journal); $diff = bcsub($amount, $event->amount); // update current repetition $repetition->currentamount = bcadd($repetition->currentamount, $diff); @@ -60,6 +53,8 @@ class UpdateJournalConnection $event->amount = $amount; $event->save(); + + return true; } } diff --git a/app/Handlers/Events/UserEventListener.php b/app/Handlers/Events/UserEventListener.php new file mode 100644 index 0000000000..6bfdbb75bd --- /dev/null +++ b/app/Handlers/Events/UserEventListener.php @@ -0,0 +1,32 @@ +allowedMimes = Config::get('firefly.allowedMimes'); $this->errors = new MessageBag; $this->messages = new MessageBag; + $this->uploadDisk = Storage::disk('upload'); } /** @@ -44,7 +51,7 @@ class AttachmentHelper implements AttachmentHelperInterface * * @return string */ - public function getAttachmentLocation(Attachment $attachment) + public function getAttachmentLocation(Attachment $attachment): string { $path = storage_path('upload') . DIRECTORY_SEPARATOR . 'at-' . $attachment->id . '.data'; @@ -54,7 +61,7 @@ class AttachmentHelper implements AttachmentHelperInterface /** * @return MessageBag */ - public function getErrors() + public function getErrors(): MessageBag { return $this->errors; } @@ -62,7 +69,7 @@ class AttachmentHelper implements AttachmentHelperInterface /** * @return MessageBag */ - public function getMessages() + public function getMessages(): MessageBag { return $this->messages; } @@ -72,9 +79,17 @@ class AttachmentHelper implements AttachmentHelperInterface * * @return bool */ - public function saveAttachmentsForModel(Model $model) + public function saveAttachmentsForModel(Model $model): bool { - $files = Input::file('attachments'); + $files = null; + try { + if (Input::hasFile('attachments')) { + $files = Input::file('attachments'); + } + } catch (TypeError $e) { + // Log it, do nothing else. + Log::error($e->getMessage()); + } if (is_array($files)) { foreach ($files as $entry) { @@ -97,7 +112,7 @@ class AttachmentHelper implements AttachmentHelperInterface * * @return bool */ - protected function hasFile(UploadedFile $file, Model $model) + protected function hasFile(UploadedFile $file, Model $model): bool { $md5 = md5_file($file->getRealPath()); $name = $file->getClientOriginalName(); @@ -115,16 +130,17 @@ class AttachmentHelper implements AttachmentHelperInterface } /** + * * @param UploadedFile $file * @param Model $model * - * @return bool|Attachment + * @return Attachment */ - protected function processFile(UploadedFile $file, Model $model) + protected function processFile(UploadedFile $file, Model $model): Attachment { $validation = $this->validateUpload($file, $model); if ($validation === false) { - return false; + return new Attachment; } $attachment = new Attachment; // create Attachment object. @@ -137,15 +153,13 @@ class AttachmentHelper implements AttachmentHelperInterface $attachment->uploaded = 0; $attachment->save(); - $path = $file->getRealPath(); // encrypt and move file to storage. - $content = file_get_contents($path); + $fileObject = $file->openFile('r'); + $fileObject->rewind(); + $content = $fileObject->fread($file->getSize()); $encrypted = Crypt::encrypt($content); // store it: - $upload = $this->getAttachmentLocation($attachment); - if (is_writable(dirname($upload))) { - file_put_contents($upload, $encrypted); - } + $this->uploadDisk->put($attachment->fileName(), $encrypted); $attachment->uploaded = 1; // update attachment $attachment->save(); @@ -165,7 +179,7 @@ class AttachmentHelper implements AttachmentHelperInterface * * @return bool */ - protected function validMime(UploadedFile $file) + protected function validMime(UploadedFile $file): bool { $mime = e($file->getMimeType()); $name = e($file->getClientOriginalName()); @@ -185,7 +199,7 @@ class AttachmentHelper implements AttachmentHelperInterface * * @return bool */ - protected function validSize(UploadedFile $file) + protected function validSize(UploadedFile $file): bool { $size = $file->getSize(); $name = e($file->getClientOriginalName()); @@ -205,7 +219,7 @@ class AttachmentHelper implements AttachmentHelperInterface * * @return bool */ - protected function validateUpload(UploadedFile $file, Model $model) + protected function validateUpload(UploadedFile $file, Model $model): bool { if (!$this->validMime($file)) { return false; diff --git a/app/Helpers/Attachments/AttachmentHelperInterface.php b/app/Helpers/Attachments/AttachmentHelperInterface.php index bcc36a642f..51e7c84628 100644 --- a/app/Helpers/Attachments/AttachmentHelperInterface.php +++ b/app/Helpers/Attachments/AttachmentHelperInterface.php @@ -1,5 +1,5 @@ accounts = new Collection; + } + + /** + * @return Collection + */ + public function getAccounts(): Collection { return $this->accounts; } /** - * @param \Illuminate\Support\Collection $accounts + * @param Collection $accounts */ - public function setAccounts($accounts) + public function setAccounts(Collection $accounts) { $this->accounts = $accounts; } /** - * @return float + * @return string */ - public function getDifference() + public function getDifference(): string { return $this->difference; } /** - * @param float $difference + * @param string $difference */ - public function setDifference($difference) + public function setDifference(string $difference) { $this->difference = $difference; } /** - * @return float + * @return string */ - public function getEnd() + public function getEnd(): string { return $this->end; } /** - * @param float $end + * @param string $end */ - public function setEnd($end) + public function setEnd(string $end) { $this->end = $end; } /** - * @return float + * @return string */ - public function getStart() + public function getStart(): string { return $this->start; } /** - * @param float $start + * @param string $start */ - public function setStart($start) + public function setStart(string $start) { $this->start = $start; } diff --git a/app/Helpers/Collection/Balance.php b/app/Helpers/Collection/Balance.php index 48d8433c2f..41db832ef7 100644 --- a/app/Helpers/Collection/Balance.php +++ b/app/Helpers/Collection/Balance.php @@ -1,5 +1,5 @@ balanceHeader; + return $this->balanceHeader ?? new BalanceHeader; } /** * @param BalanceHeader $balanceHeader */ - public function setBalanceHeader($balanceHeader) + public function setBalanceHeader(BalanceHeader $balanceHeader) { $this->balanceHeader = $balanceHeader; } /** - * @return \Illuminate\Support\Collection + * @return Collection */ - public function getBalanceLines() + public function getBalanceLines(): Collection { return $this->balanceLines; } diff --git a/app/Helpers/Collection/BalanceEntry.php b/app/Helpers/Collection/BalanceEntry.php index 7749226b82..baa2f3d17c 100644 --- a/app/Helpers/Collection/BalanceEntry.php +++ b/app/Helpers/Collection/BalanceEntry.php @@ -1,5 +1,5 @@ account; } @@ -33,39 +33,39 @@ class BalanceEntry /** * @param AccountModel $account */ - public function setAccount($account) + public function setAccount(AccountModel $account) { $this->account = $account; } /** - * @return float + * @return string */ - public function getLeft() + public function getLeft(): string { return $this->left; } /** - * @param float $left + * @param string $left */ - public function setLeft($left) + public function setLeft(string $left) { $this->left = $left; } /** - * @return float + * @return string */ - public function getSpent() + public function getSpent(): string { return $this->spent; } /** - * @param float $spent + * @param string $spent */ - public function setSpent($spent) + public function setSpent(string $spent) { $this->spent = $spent; } diff --git a/app/Helpers/Collection/BalanceHeader.php b/app/Helpers/Collection/BalanceHeader.php index 5dbe86f5f6..60ed221f7b 100644 --- a/app/Helpers/Collection/BalanceHeader.php +++ b/app/Helpers/Collection/BalanceHeader.php @@ -1,5 +1,5 @@ accounts; } diff --git a/app/Helpers/Collection/BalanceLine.php b/app/Helpers/Collection/BalanceLine.php index 0800010c42..e6157f6c06 100644 --- a/app/Helpers/Collection/BalanceLine.php +++ b/app/Helpers/Collection/BalanceLine.php @@ -1,5 +1,5 @@ balanceEntries = new Collection; + } /** @@ -46,7 +48,7 @@ class BalanceLine /** * @return Collection */ - public function getBalanceEntries() + public function getBalanceEntries(): Collection { return $this->balanceEntries; } @@ -54,7 +56,7 @@ class BalanceLine /** * @param Collection $balanceEntries */ - public function setBalanceEntries($balanceEntries) + public function setBalanceEntries(Collection $balanceEntries) { $this->balanceEntries = $balanceEntries; } @@ -62,15 +64,15 @@ class BalanceLine /** * @return BudgetModel */ - public function getBudget() + public function getBudget(): BudgetModel { - return $this->budget; + return $this->budget ?? new BudgetModel; } /** * @param BudgetModel $budget */ - public function setBudget($budget) + public function setBudget(BudgetModel $budget) { $this->budget = $budget; } @@ -78,7 +80,7 @@ class BalanceLine /** * @return int */ - public function getRole() + public function getRole(): int { return $this->role; } @@ -86,7 +88,7 @@ class BalanceLine /** * @param int $role */ - public function setRole($role) + public function setRole(int $role) { $this->role = $role; } @@ -94,9 +96,9 @@ class BalanceLine /** * @return string */ - public function getTitle() + public function getTitle(): string { - if ($this->getBudget() instanceof BudgetModel) { + if ($this->getBudget() instanceof BudgetModel && !is_null($this->getBudget()->id)) { return $this->getBudget()->name; } if ($this->getRole() == self::ROLE_DEFAULTROLE) { @@ -118,14 +120,14 @@ class BalanceLine * on the given budget/repetition. If you subtract all those amounts from the budget/repetition's * total amount, this is returned: * - * @return float + * @return string */ - public function leftOfRepetition() + public function leftOfRepetition(): string { - $start = isset($this->budget->amount) ? $this->budget->amount : 0; + $start = $this->budget->amount ?? '0'; /** @var BalanceEntry $balanceEntry */ foreach ($this->getBalanceEntries() as $balanceEntry) { - $start += $balanceEntry->getSpent(); + $start = bcadd($balanceEntry->getSpent(), $start); } return $start; diff --git a/app/Helpers/Collection/Bill.php b/app/Helpers/Collection/Bill.php index 550f8f1aeb..f5b58b36ec 100644 --- a/app/Helpers/Collection/Bill.php +++ b/app/Helpers/Collection/Bill.php @@ -1,5 +1,5 @@ bills->sortBy( function (BillLine $bill) { diff --git a/app/Helpers/Collection/BillLine.php b/app/Helpers/Collection/BillLine.php index 5091747577..8c3141170e 100644 --- a/app/Helpers/Collection/BillLine.php +++ b/app/Helpers/Collection/BillLine.php @@ -1,5 +1,5 @@ amount; + return $this->amount ?? '0'; } /** * @param string $amount */ - public function setAmount($amount) + public function setAmount(string $amount) { $this->amount = $amount; } @@ -46,7 +49,7 @@ class BillLine /** * @return BillModel */ - public function getBill() + public function getBill(): BillModel { return $this->bill; } @@ -54,7 +57,7 @@ class BillLine /** * @param BillModel $bill */ - public function setBill($bill) + public function setBill(BillModel $bill) { $this->bill = $bill; } @@ -62,7 +65,7 @@ class BillLine /** * @return string */ - public function getMax() + public function getMax(): string { return $this->max; } @@ -70,7 +73,7 @@ class BillLine /** * @param string $max */ - public function setMax($max) + public function setMax(string $max) { $this->max = $max; } @@ -78,7 +81,7 @@ class BillLine /** * @return string */ - public function getMin() + public function getMin(): string { return $this->min; } @@ -86,23 +89,39 @@ class BillLine /** * @param string $min */ - public function setMin($min) + public function setMin(string $min) { $this->min = $min; } + /** + * @return int + */ + public function getTransactionJournalId(): int + { + return $this->transactionJournalId ?? 0; + } + + /** + * @param int $transactionJournalId + */ + public function setTransactionJournalId(int $transactionJournalId) + { + $this->transactionJournalId = $transactionJournalId; + } + /** * @return boolean */ - public function isActive() + public function isActive(): bool { return $this->active; } /** - * @param boolean $active + * @param bool $active */ - public function setActive($active) + public function setActive(bool $active) { $this->active = $active; } @@ -110,15 +129,15 @@ class BillLine /** * @return boolean */ - public function isHit() + public function isHit(): bool { return $this->hit; } /** - * @param boolean $hit + * @param bool $hit */ - public function setHit($hit) + public function setHit(bool $hit) { $this->hit = $hit; } diff --git a/app/Helpers/Collection/Budget.php b/app/Helpers/Collection/Budget.php index 53548291de..92d864eb06 100644 --- a/app/Helpers/Collection/Budget.php +++ b/app/Helpers/Collection/Budget.php @@ -1,5 +1,5 @@ budgeted = bcadd($this->budgeted, $add); } /** - * @param float $add + * @param string $add */ - public function addLeft($add) + public function addLeft(string $add) { - $add = strval(round($add, 2)); - bcscale(2); + $add = strval(round($add, 2)); $this->left = bcadd($this->left, $add); } /** - * @param float $add + * @param string $add */ - public function addOverspent($add) + public function addOverspent(string $add) { - $add = strval(round($add, 2)); - bcscale(2); + $add = strval(round($add, 2)); $this->overspent = bcadd($this->overspent, $add); } /** - * @param float $add + * @param string $add */ - public function addSpent($add) + public function addSpent(string $add) { - $add = strval(round($add, 2)); - bcscale(2); + $add = strval(round($add, 2)); $this->spent = bcadd($this->spent, $add); } /** * @return \Illuminate\Support\Collection */ - public function getBudgetLines() + public function getBudgetLines(): Collection { return $this->budgetLines; } @@ -91,7 +87,7 @@ class Budget /** * @return string */ - public function getBudgeted() + public function getBudgeted(): string { return $this->budgeted; } @@ -99,7 +95,7 @@ class Budget /** * @param string $budgeted */ - public function setBudgeted($budgeted) + public function setBudgeted(string $budgeted) { $this->budgeted = $budgeted; } @@ -107,7 +103,7 @@ class Budget /** * @return string */ - public function getLeft() + public function getLeft(): string { return $this->left; } @@ -115,7 +111,7 @@ class Budget /** * @param string $left */ - public function setLeft($left) + public function setLeft(string $left) { $this->left = $left; } @@ -123,7 +119,7 @@ class Budget /** * @return string */ - public function getOverspent() + public function getOverspent(): string { return $this->overspent; } @@ -131,7 +127,7 @@ class Budget /** * @param string $overspent */ - public function setOverspent($overspent) + public function setOverspent(string $overspent) { $this->overspent = strval(round($overspent, 2)); } @@ -139,7 +135,7 @@ class Budget /** * @return string */ - public function getSpent() + public function getSpent(): string { return $this->spent; } @@ -147,7 +143,7 @@ class Budget /** * @param string $spent */ - public function setSpent($spent) + public function setSpent(string $spent) { $this->spent = strval(round($spent, 2)); } diff --git a/app/Helpers/Collection/BudgetLine.php b/app/Helpers/Collection/BudgetLine.php index f26950f9f9..ecda6ac7ca 100644 --- a/app/Helpers/Collection/BudgetLine.php +++ b/app/Helpers/Collection/BudgetLine.php @@ -1,5 +1,5 @@ budget; + return $this->budget ?? new BudgetModel; } /** * @param BudgetModel $budget */ - public function setBudget($budget) + public function setBudget(BudgetModel $budget) { $this->budget = $budget; } /** - * @return float + * @return string */ - public function getBudgeted() + public function getBudgeted(): string { return $this->budgeted; } /** - * @param float $budgeted + * @param string $budgeted */ - public function setBudgeted($budgeted) + public function setBudgeted(string $budgeted) { $this->budgeted = $budgeted; } /** - * @return float + * @return string */ - public function getLeft() + public function getLeft(): string { return $this->left; } /** - * @param float $left + * @param string $left */ - public function setLeft($left) + public function setLeft(string $left) { $this->left = $left; } /** - * @return float + * @return string */ - public function getOverspent() + public function getOverspent(): string { return $this->overspent; } /** - * @param float $overspent + * @param string $overspent */ - public function setOverspent($overspent) + public function setOverspent(string $overspent) { $this->overspent = $overspent; } @@ -95,31 +95,31 @@ class BudgetLine /** * @return LimitRepetition */ - public function getRepetition() + public function getRepetition(): LimitRepetition { - return $this->repetition; + return $this->repetition ?? new LimitRepetition; } /** * @param LimitRepetition $repetition */ - public function setRepetition($repetition) + public function setRepetition(LimitRepetition $repetition) { $this->repetition = $repetition; } /** - * @return float + * @return string */ - public function getSpent() + public function getSpent(): string { return $this->spent; } /** - * @param float $spent + * @param string $spent */ - public function setSpent($spent) + public function setSpent(string $spent) { $this->spent = $spent; } diff --git a/app/Helpers/Collection/Category.php b/app/Helpers/Collection/Category.php index 6e243a7631..b8196fe05a 100644 --- a/app/Helpers/Collection/Category.php +++ b/app/Helpers/Collection/Category.php @@ -1,5 +1,5 @@ total = bcadd($this->total, $add); } /** * @return Collection */ - public function getCategories() + public function getCategories(): Collection { $set = $this->categories->sortBy( function (CategoryModel $category) { @@ -69,7 +68,7 @@ class Category /** * @return string */ - public function getTotal() + public function getTotal(): string { return strval(round($this->total, 2)); } diff --git a/app/Helpers/Collection/Expense.php b/app/Helpers/Collection/Expense.php index ce489c5118..b241f04f9f 100644 --- a/app/Helpers/Collection/Expense.php +++ b/app/Helpers/Collection/Expense.php @@ -1,5 +1,5 @@ account_id; $amount = strval(round($entry->journalAmount, 2)); @@ -58,11 +57,10 @@ class Expense } /** - * @param $add + * @param string $add */ - public function addToTotal($add) + public function addToTotal(string $add) { - bcscale(2); $add = strval(round($add, 2)); @@ -80,7 +78,7 @@ class Expense /** * @return Collection */ - public function getExpenses() + public function getExpenses(): Collection { $set = $this->expenses->sortBy( function (stdClass $object) { @@ -94,7 +92,7 @@ class Expense /** * @return string */ - public function getTotal() + public function getTotal(): string { return strval(round($this->total, 2)); } diff --git a/app/Helpers/Collection/Income.php b/app/Helpers/Collection/Income.php index 6a66de8fef..17017e5129 100644 --- a/app/Helpers/Collection/Income.php +++ b/app/Helpers/Collection/Income.php @@ -1,5 +1,5 @@ id = $accountId; $this->incomes->put($accountId, $newObject); } else { - bcscale(2); $existing = $this->incomes->get($accountId); $existing->amount = bcadd($existing->amount, $entry->journalAmount); $existing->count++; @@ -54,19 +53,18 @@ class Income } /** - * @param $add + * @param string $add */ - public function addToTotal($add) + public function addToTotal(string $add) { - $add = strval(round($add, 2)); - bcscale(2); + $add = strval(round($add, 2)); $this->total = bcadd($this->total, $add); } /** * @return Collection */ - public function getIncomes() + public function getIncomes(): Collection { $set = $this->incomes->sortByDesc( function (stdClass $object) { @@ -80,7 +78,7 @@ class Income /** * @return string */ - public function getTotal() + public function getTotal(): string { return strval(round($this->total, 2)); } diff --git a/app/Helpers/Csv/Converter/AccountId.php b/app/Helpers/Csv/Converter/AccountId.php index c489fa36a4..00912809bd 100644 --- a/app/Helpers/Csv/Converter/AccountId.php +++ b/app/Helpers/Csv/Converter/AccountId.php @@ -1,4 +1,5 @@ mapped[$this->index][$this->value])) { @@ -30,6 +31,9 @@ class AccountId extends BasicConverter implements ConverterInterface if (!is_null($account)) { Log::debug('Found ' . $account->accountType->type . ' named "******" with ID: ' . $this->value . ' (not mapped) '); + } else { + // new account to prevent TypeErrors. + $account = new Account; } } diff --git a/app/Helpers/Csv/Converter/Amount.php b/app/Helpers/Csv/Converter/Amount.php index 7ec25ce17e..6aade561ab 100644 --- a/app/Helpers/Csv/Converter/Amount.php +++ b/app/Helpers/Csv/Converter/Amount.php @@ -1,5 +1,5 @@ value)) { - return $this->value; + return strval($this->value); } - return 0; + return '0'; } } diff --git a/app/Helpers/Csv/Converter/AmountComma.php b/app/Helpers/Csv/Converter/AmountComma.php index 5fed5587b9..37b4d95841 100644 --- a/app/Helpers/Csv/Converter/AmountComma.php +++ b/app/Helpers/Csv/Converter/AmountComma.php @@ -1,5 +1,5 @@ value); + $value = str_replace(',', '.', strval($this->value)); if (is_numeric($value)) { - return floatval($value); + return strval($value); } - return 0; + return '0'; } } diff --git a/app/Helpers/Csv/Converter/AssetAccountIban.php b/app/Helpers/Csv/Converter/AssetAccountIban.php index 311e529a47..d506b2d052 100644 --- a/app/Helpers/Csv/Converter/AssetAccountIban.php +++ b/app/Helpers/Csv/Converter/AssetAccountIban.php @@ -1,10 +1,10 @@ mapped[$this->index][$this->value])) { $account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]); @@ -27,32 +28,41 @@ class AssetAccountIban extends BasicConverter implements ConverterInterface } if (strlen($this->value) > 0) { // find or create new account: - $account = $this->findAccount(); - $accountType = AccountType::where('type', 'Asset account')->first(); + $account = $this->findAccount(); - if (is_null($account)) { + if (is_null($account->id)) { // create it if doesn't exist. - $account = Account::firstOrCreateEncrypted( - [ - 'name' => $this->value, - 'iban' => $this->value, - 'user_id' => Auth::user()->id, - 'account_type_id' => $accountType->id, - 'active' => 1, - ] - ); + + $repository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + $accountData = [ + 'name' => $this->value, + 'accountType' => 'asset', + 'virtualBalance' => 0, + 'virtualBalanceCurrency' => 1, // hard coded. + 'active' => true, + 'user' => Auth::user()->id, + 'iban' => null, + 'accountNumber' => $this->value, + 'accountRole' => null, + 'openingBalance' => 0, + 'openingBalanceDate' => new Carbon, + 'openingBalanceCurrency' => 1, // hard coded. + + ]; + + $account = $repository->store($accountData); } return $account; } - return null; + return new Account; } /** - * @return Account|null + * @return Account */ - protected function findAccount() + protected function findAccount(): Account { $set = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']); /** @var Account $entry */ @@ -63,6 +73,6 @@ class AssetAccountIban extends BasicConverter implements ConverterInterface } } - return null; + return new Account; } } diff --git a/app/Helpers/Csv/Converter/AssetAccountName.php b/app/Helpers/Csv/Converter/AssetAccountName.php index 87804875af..407e54fc6d 100644 --- a/app/Helpers/Csv/Converter/AssetAccountName.php +++ b/app/Helpers/Csv/Converter/AssetAccountName.php @@ -1,10 +1,10 @@ first(); - $set = Auth::user()->accounts()->accountTypeIn(['Asset account', 'Default account'])->get(); + $set = Auth::user()->accounts()->accountTypeIn(['Asset account', 'Default account'])->get(); /** @var Account $entry */ foreach ($set as $entry) { if ($entry->name == $this->value) { @@ -36,15 +35,25 @@ class AssetAccountName extends BasicConverter implements ConverterInterface } // create it if doesnt exist. - $account = Account::firstOrCreateEncrypted( - [ - 'name' => $this->value, - 'iban' => '', - 'user_id' => Auth::user()->id, - 'account_type_id' => $accountType->id, - 'active' => 1, - ] - ); + + $repository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + $accountData = [ + 'name' => $this->value, + 'accountType' => 'asset', + 'virtualBalance' => 0, + 'virtualBalanceCurrency' => 1, // hard coded. + 'active' => true, + 'user' => Auth::user()->id, + 'iban' => null, + 'accountNumber' => $this->value, + 'accountRole' => null, + 'openingBalance' => 0, + 'openingBalanceDate' => new Carbon, + 'openingBalanceCurrency' => 1, // hard coded. + + ]; + + $account = $repository->store($accountData); return $account; } diff --git a/app/Helpers/Csv/Converter/AssetAccountNumber.php b/app/Helpers/Csv/Converter/AssetAccountNumber.php new file mode 100644 index 0000000000..803fc9763f --- /dev/null +++ b/app/Helpers/Csv/Converter/AssetAccountNumber.php @@ -0,0 +1,89 @@ +mapped[$this->index][$this->value])) { + $account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]); + + return $account; + } + // if not, search for it (or create it): + $value = $this->value ?? ''; + if (strlen($value) > 0) { + // find or create new account: + $account = $this->findAccount(); + + if (is_null($account->id)) { + // create it if doesn't exist. + $repository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + + + $accountData = [ + 'name' => $this->value, + 'accountType' => 'asset', + 'virtualBalance' => 0, + 'virtualBalanceCurrency' => 1, // hard coded. + 'active' => true, + 'user' => Auth::user()->id, + 'iban' => null, + 'accountNumber' => $this->value, + 'accountRole' => null, + 'openingBalance' => 0, + 'openingBalanceDate' => new Carbon, + 'openingBalanceCurrency' => 1, // hard coded. + + ]; + + $account = $repository->store($accountData); + } + + return $account; + } + + return null; + } + + /** + * @return Account + */ + protected function findAccount(): Account + { + $set = Auth::user()->accounts()->with(['accountmeta'])->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']); + /** @var Account $entry */ + foreach ($set as $entry) { + $accountNumber = $entry->getMeta('accountNumber'); + if ($accountNumber == $this->value) { + + return $entry; + } + } + + return new Account; + } +} diff --git a/app/Helpers/Csv/Converter/BasicConverter.php b/app/Helpers/Csv/Converter/BasicConverter.php index 2c7bff6f2a..b1a262cae8 100644 --- a/app/Helpers/Csv/Converter/BasicConverter.php +++ b/app/Helpers/Csv/Converter/BasicConverter.php @@ -1,5 +1,5 @@ mapped[$this->index][$this->value])) { - $budget = Auth::user()->budgets()->find($this->mapped[$this->index][$this->value]); + $budget = Auth::user()->budgets()->find($this->mapped[$this->index][$this->value]); // see issue #180 } else { - $budget = Budget::firstOrCreateEncrypted( - [ - 'name' => $this->value, - 'user_id' => Auth::user()->id, - 'active' => true, - ] - ); + $repository = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); + $budget = $repository->store(['name' => $this->value, 'user' => Auth::user()->id]); } return $budget; diff --git a/app/Helpers/Csv/Converter/CategoryId.php b/app/Helpers/Csv/Converter/CategoryId.php index c5dcf760d4..f205f9edfe 100644 --- a/app/Helpers/Csv/Converter/CategoryId.php +++ b/app/Helpers/Csv/Converter/CategoryId.php @@ -1,4 +1,5 @@ mapped[$this->index][$this->value])) { $category = Auth::user()->categories()->find($this->mapped[$this->index][$this->value]); } else { - $category = Category::firstOrCreateEncrypted( + $category = Category::firstOrCreateEncrypted( // See issue #180 [ 'name' => $this->value, 'user_id' => Auth::user()->id, diff --git a/app/Helpers/Csv/Converter/ConverterInterface.php b/app/Helpers/Csv/Converter/ConverterInterface.php index 1eb2e37db9..643d17b6c1 100644 --- a/app/Helpers/Csv/Converter/ConverterInterface.php +++ b/app/Helpers/Csv/Converter/ConverterInterface.php @@ -1,5 +1,5 @@ value); } catch (InvalidArgumentException $e) { diff --git a/app/Helpers/Csv/Converter/Description.php b/app/Helpers/Csv/Converter/Description.php index bb5626e251..98cfd1b4bf 100644 --- a/app/Helpers/Csv/Converter/Description.php +++ b/app/Helpers/Csv/Converter/Description.php @@ -1,5 +1,5 @@ data['description'] . ' ' . $this->value); + $description = $this->data['description'] ?? ''; + + return trim($description . ' ' . $this->value); } } diff --git a/app/Helpers/Csv/Converter/INGDebetCredit.php b/app/Helpers/Csv/Converter/INGDebetCredit.php new file mode 100644 index 0000000000..e41aee16ac --- /dev/null +++ b/app/Helpers/Csv/Converter/INGDebetCredit.php @@ -0,0 +1,34 @@ +value === 'Af') { + return -1; + } + + return 1; + } +} diff --git a/app/Helpers/Csv/Converter/Ignore.php b/app/Helpers/Csv/Converter/Ignore.php index a9dff94088..30cf747a86 100644 --- a/app/Helpers/Csv/Converter/Ignore.php +++ b/app/Helpers/Csv/Converter/Ignore.php @@ -1,5 +1,5 @@ value); foreach ($strings as $string) { - $tag = Tag::firstOrCreateEncrypted( + $tag = Tag::firstOrCreateEncrypted( // See issue #180 [ 'tag' => $string, 'tagMode' => 'nothing', diff --git a/app/Helpers/Csv/Converter/TagsSpace.php b/app/Helpers/Csv/Converter/TagsSpace.php index 323f6005cc..c0e7b5c4f8 100644 --- a/app/Helpers/Csv/Converter/TagsSpace.php +++ b/app/Helpers/Csv/Converter/TagsSpace.php @@ -1,5 +1,5 @@ value); foreach ($strings as $string) { - $tag = Tag::firstOrCreateEncrypted( + $tag = Tag::firstOrCreateEncrypted( // See issue #180 [ 'tag' => $string, 'tagMode' => 'nothing', diff --git a/app/Helpers/Csv/Data.php b/app/Helpers/Csv/Data.php index 32e1ca4477..b45edd5211 100644 --- a/app/Helpers/Csv/Data.php +++ b/app/Helpers/Csv/Data.php @@ -1,9 +1,11 @@ csvFileContent; + return $this->csvFileContent ?? ''; } /** * * @param string $csvFileContent */ - public function setCsvFileContent($csvFileContent) + public function setCsvFileContent(string $csvFileContent) { $this->csvFileContent = $csvFileContent; } @@ -82,7 +84,7 @@ class Data * * @param string $csvFileLocation */ - public function setCsvFileLocation($csvFileLocation) + public function setCsvFileLocation(string $csvFileLocation) { Session::put('csv-file', $csvFileLocation); $this->csvFileLocation = $csvFileLocation; @@ -99,9 +101,9 @@ class Data /** * - * @param mixed $dateFormat + * @param string $dateFormat */ - public function setDateFormat($dateFormat) + public function setDateFormat(string $dateFormat) { Session::put('csv-date-format', $dateFormat); $this->dateFormat = $dateFormat; @@ -120,7 +122,7 @@ class Data * * @param string $delimiter */ - public function setDelimiter($delimiter) + public function setDelimiter(string $delimiter) { Session::put('csv-delimiter', $delimiter); $this->delimiter = $delimiter; @@ -170,7 +172,7 @@ class Data */ public function getReader() { - if (strlen($this->csvFileContent) === 0) { + if (!is_null($this->csvFileContent) && strlen($this->csvFileContent) === 0) { $this->loadCsvFile(); } @@ -233,7 +235,7 @@ class Data * * @param bool $hasHeaders */ - public function setHasHeaders($hasHeaders) + public function setHasHeaders(bool $hasHeaders) { Session::put('csv-has-headers', $hasHeaders); $this->hasHeaders = $hasHeaders; @@ -243,7 +245,7 @@ class Data * * @param int $importAccount */ - public function setImportAccount($importAccount) + public function setImportAccount(int $importAccount) { Session::put('csv-import-account', $importAccount); $this->importAccount = $importAccount; @@ -252,7 +254,8 @@ class Data protected function loadCsvFile() { $file = $this->getCsvFileLocation(); - $content = file_get_contents($file); + $disk = Storage::disk('upload'); + $content = $disk->get($file); $contentDecrypted = Crypt::decrypt($content); $this->setCsvFileContent($contentDecrypted); } @@ -260,63 +263,63 @@ class Data protected function sessionCsvFileLocation() { if (Session::has('csv-file')) { - $this->csvFileLocation = (string)Session::get('csv-file'); + $this->csvFileLocation = (string)session('csv-file'); } } protected function sessionDateFormat() { if (Session::has('csv-date-format')) { - $this->dateFormat = (string)Session::get('csv-date-format'); + $this->dateFormat = (string)session('csv-date-format'); } } protected function sessionDelimiter() { if (Session::has('csv-delimiter')) { - $this->delimiter = Session::get('csv-delimiter'); + $this->delimiter = session('csv-delimiter'); } } protected function sessionHasHeaders() { if (Session::has('csv-has-headers')) { - $this->hasHeaders = (bool)Session::get('csv-has-headers'); + $this->hasHeaders = (bool)session('csv-has-headers'); } } protected function sessionImportAccount() { if (Session::has('csv-import-account')) { - $this->importAccount = intval(Session::get('csv-import-account')); + $this->importAccount = intval(session('csv-import-account')); } } protected function sessionMap() { if (Session::has('csv-map')) { - $this->map = (array)Session::get('csv-map'); + $this->map = (array)session('csv-map'); } } protected function sessionMapped() { if (Session::has('csv-mapped')) { - $this->mapped = (array)Session::get('csv-mapped'); + $this->mapped = (array)session('csv-mapped'); } } protected function sessionRoles() { if (Session::has('csv-roles')) { - $this->roles = (array)Session::get('csv-roles'); + $this->roles = (array)session('csv-roles'); } } protected function sessionSpecifix() { if (Session::has('csv-specifix')) { - $this->specifix = (array)Session::get('csv-specifix'); + $this->specifix = (array)session('csv-specifix'); } } } diff --git a/app/Helpers/Csv/Importer.php b/app/Helpers/Csv/Importer.php index 0386f71819..ac1bcdffb4 100644 --- a/app/Helpers/Csv/Importer.php +++ b/app/Helpers/Csv/Importer.php @@ -1,5 +1,5 @@ data = $data; } @@ -147,7 +147,6 @@ class Importer */ protected function createTransactionJournal() { - bcscale(2); $date = $this->importData['date']; if (is_null($this->importData['date'])) { $date = $this->importData['date-rent']; @@ -169,7 +168,7 @@ class Importer // second transaction $accountId = $this->importData['opposing-account-object']->id; // create second transaction: - $amount = bcmul($this->importData['amount'], -1); + $amount = bcmul($this->importData['amount'], '-1'); $transaction = Transaction::create(['transaction_journal_id' => $journal->id, 'account_id' => $accountId, 'amount' => $amount]); $errors = $transaction->getErrors()->merge($errors); } @@ -187,7 +186,7 @@ class Importer // some debug info: $journalId = $journal->id; - $type = $journal->getTransactionType(); + $type = $journal->transaction_type_type ?? $journal->transactionType->type; /** @var Account $asset */ $asset = $this->importData['asset-account-object']; /** @var Account $opposing */ @@ -195,7 +194,7 @@ class Importer Log::info('Created journal #' . $journalId . ' of type ' . $type . '!'); Log::info('Asset account #' . $asset->id . ' lost/gained: ' . $this->importData['amount']); - Log::info($opposing->accountType->type . ' #' . $opposing->id . ' lost/gained: ' . bcmul($this->importData['amount'], -1)); + Log::info($opposing->accountType->type . ' #' . $opposing->id . ' lost/gained: ' . bcmul($this->importData['amount'], '-1')); return $journal; } @@ -218,17 +217,17 @@ class Importer } /** - * @param $row + * @param array $row * * @throws FireflyException * @return string|bool */ - protected function importRow($row) + protected function importRow(array $row) { $data = $this->getFiller(); // These fields are necessary to create a new transaction journal. Some are optional foreach ($row as $index => $value) { - $role = isset($this->roles[$index]) ? $this->roles[$index] : '_ignore'; + $role = $this->roles[$index] ?? '_ignore'; $class = Config::get('csv.roles.' . $role . '.converter'); $field = Config::get('csv.roles.' . $role . '.field'); @@ -266,7 +265,7 @@ class Importer * * @return bool */ - protected function parseRow($index) + protected function parseRow(int $index) { return (($this->data->hasHeaders() && $index >= 1) || !$this->data->hasHeaders()); } @@ -296,7 +295,8 @@ class Importer foreach ($set as $className) { /** @var PostProcessorInterface $postProcessor */ $postProcessor = app('FireflyIII\Helpers\Csv\PostProcessing\\' . $className); - $postProcessor->setData($this->importData); + $array = $this->importData ?? []; + $postProcessor->setData($array); Log::debug('Now post-process processor named ' . $className . ':'); $this->importData = $postProcessor->process(); } @@ -343,7 +343,9 @@ class Importer */ protected function validateData() { - if (is_null($this->importData['date']) && is_null($this->importData['date-rent'])) { + $date = $this->importData['date'] ?? null; + $rentDate = $this->importData['date-rent'] ?? null; + if (is_null($date) && is_null($rentDate)) { return 'No date value for this row.'; } if (is_null($this->importData['opposing-account-object'])) { @@ -368,8 +370,8 @@ class Importer /** @var Rule $rule */ foreach ($group->rules as $rule) { - $processor = new Processor($rule, $journal); - $processor->handle(); + $processor = Processor::make($rule); + $processor->handleTransactionJournal($journal); if ($rule->stop_processing) { break; } diff --git a/app/Helpers/Csv/Mapper/AnyAccount.php b/app/Helpers/Csv/Mapper/AnyAccount.php index dcfaefeec5..573e025f04 100644 --- a/app/Helpers/Csv/Mapper/AnyAccount.php +++ b/app/Helpers/Csv/Mapper/AnyAccount.php @@ -1,5 +1,5 @@ name; - if (strlen($account->iban) > 0) { + $iban = $account->iban ?? ''; + if (strlen($iban) > 0) { $name .= ' (' . $account->iban . ')'; } $list[$account->id] = $name; diff --git a/app/Helpers/Csv/Mapper/Bill.php b/app/Helpers/Csv/Mapper/Bill.php index f94c7ccd7e..d0f9cb8c3d 100644 --- a/app/Helpers/Csv/Mapper/Bill.php +++ b/app/Helpers/Csv/Mapper/Bill.php @@ -1,5 +1,5 @@ data['amount'] = bcmul($this->data['amount'], $this->data['amount-modifier']); + $amount = $this->data['amount'] ?? '0'; + $modifier = strval($this->data['amount-modifier']); + $this->data['amount'] = bcmul($amount, $modifier); return $this->data; } diff --git a/app/Helpers/Csv/PostProcessing/AssetAccount.php b/app/Helpers/Csv/PostProcessing/AssetAccount.php index a3a91f2de4..7ee7986b76 100644 --- a/app/Helpers/Csv/PostProcessing/AssetAccount.php +++ b/app/Helpers/Csv/PostProcessing/AssetAccount.php @@ -1,8 +1,9 @@ checkIbanString(); if (!is_null($result)) { return $result; } + // no object still? maybe we can find the account by name. $result = $this->checkNameString(); if (!is_null($result)) { return $result; } + // still nothing? Perhaps the account number can lead us to an account: + $result = $this->checkAccountNumberString(); + if (!is_null($result)) { + return $result; + } return null; } @@ -51,17 +59,18 @@ class AssetAccount implements PostProcessorInterface } /** - * @return array + * @return array|null */ - protected function checkIdNameObject() + protected function checkAccountNumberString() { - if ($this->data['asset-account-id'] instanceof Account) { // first priority. try to find the account based on ID, if any - $this->data['asset-account-object'] = $this->data['asset-account-id']; + $accountNumber = $this->data['asset-account-number'] ?? null; + if ($accountNumber instanceof Account) { // fourth: try to find account based on name, if any. + $this->data['asset-account-object'] = $accountNumber; return $this->data; } - if ($this->data['asset-account-iban'] instanceof Account) { // second: try to find the account based on IBAN, if any. - $this->data['asset-account-object'] = $this->data['asset-account-iban']; + if (is_string($accountNumber)) { // it's an actual account number + $this->data['asset-account-object'] = $this->parseAccountNumberString(); return $this->data; } @@ -74,8 +83,9 @@ class AssetAccount implements PostProcessorInterface */ protected function checkIbanString() { + $iban = $this->data['asset-account-iban'] ?? ''; $rules = ['iban' => 'iban']; - $check = ['iban' => $this->data['asset-account-iban']]; + $check = ['iban' => $iban]; $validator = Validator::make($check, $rules); if (!$validator->fails()) { $this->data['asset-account-object'] = $this->parseIbanString(); @@ -87,21 +97,52 @@ class AssetAccount implements PostProcessorInterface } /** - * @return Account|null + * @return array */ - protected function parseIbanString() + protected function checkIdNameObject() { - // create by name and/or iban. - $accounts = Auth::user()->accounts()->get(); - foreach ($accounts as $entry) { - if ($entry->iban == $this->data['asset-account-iban']) { + $accountId = $this->data['asset-account-id'] ?? null; + $accountIban = $this->data['asset-account-iban'] ?? null; + $accountNumber = $this->data['asset-account-number'] ?? null; + if ($accountId instanceof Account) { // first priority. try to find the account based on ID, if any + $this->data['asset-account-object'] = $accountId; - return $entry; - } + return $this->data; } - $account = $this->createAccount(); + if ($accountIban instanceof Account) { // second: try to find the account based on IBAN, if any. + $this->data['asset-account-object'] = $accountIban; - return $account; + return $this->data; + } + + if ($accountNumber instanceof Account) { // second: try to find the account based on account number, if any. + $this->data['asset-account-object'] = $accountNumber; + + return $this->data; + } + + + return null; + } + + /** + * @return array|null + */ + protected function checkNameString() + { + $accountName = $this->data['asset-account-name'] ?? null; + if ($accountName instanceof Account) { // third: try to find account based on name, if any. + $this->data['asset-account-object'] = $accountName; + + return $this->data; + } + if (is_string($accountName)) { + $this->data['asset-account-object'] = $this->parseNameString(); + + return $this->data; + } + + return null; } /** @@ -110,16 +151,17 @@ class AssetAccount implements PostProcessorInterface protected function createAccount() { $accountType = $this->getAccountType(); + $name = $this->data['asset-account-name'] ?? ''; + $iban = $this->data['asset-account-iban'] ?? ''; - // create if not exists: - $name = is_string($this->data['asset-account-name']) && strlen($this->data['asset-account-name']) > 0 ? $this->data['asset-account-name'] - : $this->data['asset-account-iban']; + // create if not exists: // See issue #180 + $name = strlen($name) > 0 ? $name : $iban; $account = Account::firstOrCreateEncrypted( [ 'user_id' => Auth::user()->id, 'account_type_id' => $accountType->id, 'name' => $name, - 'iban' => $this->data['asset-account-iban'], + 'iban' => $iban, 'active' => true, ] ); @@ -137,22 +179,22 @@ class AssetAccount implements PostProcessorInterface } /** - * @return array|null + * @return Account|null */ - protected function checkNameString() + protected function parseIbanString() { - if ($this->data['asset-account-name'] instanceof Account) { // third: try to find account based on name, if any. - $this->data['asset-account-object'] = $this->data['asset-account-name']; + // create by name and/or iban. + $iban = $this->data['asset-account-iban'] ?? ''; + $accounts = Auth::user()->accounts()->get(); + foreach ($accounts as $entry) { + if ($iban !== '' && $entry->iban === $iban) { - return $this->data; + return $entry; + } } - if (is_string($this->data['asset-account-name'])) { - $this->data['asset-account-object'] = $this->parseNameString(); + $account = $this->createAccount(); - return $this->data; - } - - return null; + return $account; } /** @@ -170,6 +212,7 @@ class AssetAccount implements PostProcessorInterface } } // create if not exists: + // See issue #180 $account = Account::firstOrCreateEncrypted( [ 'user_id' => Auth::user()->id, @@ -182,4 +225,43 @@ class AssetAccount implements PostProcessorInterface return $account; } + + /** + * @return Account|null + */ + private function parseAccountNumberString() + { + $accountNumber = $this->data['asset-account-number'] ?? ''; + $accountType = $this->getAccountType(); + $accounts = Auth::user()->accounts()->with(['accountmeta'])->where('account_type_id', $accountType->id)->get(); + /** @var Account $entry */ + foreach ($accounts as $entry) { + $metaFieldValue = $entry->getMeta('accountNumber'); + if ($metaFieldValue === $accountNumber && $metaFieldValue !== '') { + Log::debug('Found an asset account with this account number (#' . $entry->id . ')'); + + return $entry; + } + } + // create new if not exists and return that one: + /** @var \FireflyIII\Repositories\Account\AccountRepositoryInterface $repository */ + $repository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + $accountData = [ + 'name' => $accountNumber, + 'accountType' => 'asset', + 'virtualBalance' => 0, + 'virtualBalanceCurrency' => 1, // hard coded. + 'active' => true, + 'user' => Auth::user()->id, + 'iban' => null, + 'accountNumber' => $accountNumber, + 'accountRole' => null, + 'openingBalance' => 0, + 'openingBalanceDate' => new Carbon, + 'openingBalanceCurrency' => 1, // hard coded. + ]; + $account = $repository->store($accountData); + + return $account; + } } diff --git a/app/Helpers/Csv/PostProcessing/Bill.php b/app/Helpers/Csv/PostProcessing/Bill.php index 22a1993edd..de81b8b3c4 100644 --- a/app/Helpers/Csv/PostProcessing/Bill.php +++ b/app/Helpers/Csv/PostProcessing/Bill.php @@ -1,5 +1,5 @@ data['description'] = trim($this->data['description']); + $description = $this->data['description'] ?? ''; + $this->data['description'] = trim($description); if (strlen($this->data['description']) == 0) { $this->data['description'] = trans('firefly.csv_empty_description'); } diff --git a/app/Helpers/Csv/PostProcessing/OpposingAccount.php b/app/Helpers/Csv/PostProcessing/OpposingAccount.php index 2a0e3f6e2b..0bc038bba3 100644 --- a/app/Helpers/Csv/PostProcessing/OpposingAccount.php +++ b/app/Helpers/Csv/PostProcessing/OpposingAccount.php @@ -1,5 +1,5 @@ data['opposing-account-name']) && strlen($this->data['opposing-account-name']) > 0 ? $this->data['opposing-account-name'] : $this->data['opposing-account-iban']; - $account = Account::firstOrCreateEncrypted( + $account = Account::firstOrCreateEncrypted( // See issue #180 [ 'user_id' => Auth::user()->id, 'account_type_id' => $accountType->id, @@ -195,7 +195,7 @@ class OpposingAccount implements PostProcessorInterface } } // create if not exists: - $account = Account::firstOrCreateEncrypted( + $account = Account::firstOrCreateEncrypted( // See issue #180 [ 'user_id' => Auth::user()->id, 'account_type_id' => $accountType->id, diff --git a/app/Helpers/Csv/PostProcessing/PostProcessorInterface.php b/app/Helpers/Csv/PostProcessing/PostProcessorInterface.php index 88c0b60559..a6a793c3d5 100644 --- a/app/Helpers/Csv/PostProcessing/PostProcessorInterface.php +++ b/app/Helpers/Csv/PostProcessing/PostProcessorInterface.php @@ -1,5 +1,5 @@ data = $data; } @@ -57,7 +57,7 @@ class AbnAmroDescription extends Specifix implements SpecifixInterface /** * @param array $row */ - public function setRow($row) + public function setRow(array $row) { $this->row = $row; } @@ -95,7 +95,12 @@ class AbnAmroDescription extends Specifix implements SpecifixInterface // description and opposing account will be the same. $this->data['opposing-account-name'] = $matches[4]; - $this->data['description'] = $matches[4]; + + if ($matches[1] == 'GEA') { + $this->data['description'] = 'GEA ' . $matches[4]; + } else { + $this->data['description'] = $matches[4]; + } return true; } @@ -114,20 +119,28 @@ class AbnAmroDescription extends Specifix implements SpecifixInterface if (preg_match('/^SEPA(.{28})/', $this->data['description'], $matches)) { Log::debug('AbnAmroSpecifix: Description is structured as SEPA plain description.'); + $type = $matches[1]; + $reference = ''; + $name = ''; + $newDescription = ''; + // SEPA plain descriptions contain several key-value pairs, split by a colon - preg_match_all('/([A-Za-z]+(?=:\s)):\s([A-Za-z 0-9._#-]+(?=\s))/', $this->data['description'], $matches, PREG_SET_ORDER); + preg_match_all('/([A-Za-z]+(?=:\s)):\s([A-Za-z 0-9._#-]+(?=\s|$))/', $this->data['description'], $matches, PREG_SET_ORDER); if (is_array($matches)) { foreach ($matches as $match) { $key = $match[1]; $value = trim($match[2]); - + Log::debug('SEPA: ' . $key . ' - ' . $value); switch (strtoupper($key)) { case 'OMSCHRIJVING': - $this->data['description'] = $value; + $newDescription = $value; break; case 'NAAM': - $this->data['opposing-account-name'] = $value; + $this->data['opposing-account-name'] = $name = $value; + break; + case 'KENMERK': + $reference = $value; break; case 'IBAN': $this->data['opposing-account-iban'] = $value; @@ -138,6 +151,14 @@ class AbnAmroDescription extends Specifix implements SpecifixInterface } } + // Set a new description for the current transaction. If none was given + // set the description to type, name and reference + if ($newDescription) { + $this->data['description'] = $newDescription; + } else { + $this->data['description'] = sprintf('%s - %s (%s)', $type, $name, $reference); + } + return true; } @@ -155,6 +176,13 @@ class AbnAmroDescription extends Specifix implements SpecifixInterface if (preg_match_all('!\/([A-Z]{3,4})\/([^/]*)!', $this->data['description'], $matches, PREG_SET_ORDER)) { Log::debug('AbnAmroSpecifix: Description is structured as TRTP format.'); + $type = ''; + $name = ''; + $reference = ''; + $newDescription = ''; + + // Search for properties specified in the TRTP format. If no description + // is provided, use the type, name and reference as new description if (is_array($matches)) { foreach ($matches as $match) { $key = $match[1]; @@ -162,18 +190,32 @@ class AbnAmroDescription extends Specifix implements SpecifixInterface switch (strtoupper($key)) { case 'NAME': - $this->data['opposing-account-name'] = $value; + $this->data['opposing-account-name'] = $name = $value; break; case 'REMI': - $this->data['description'] = $value; + $newDescription = $value; break; case 'IBAN': $this->data['opposing-account-iban'] = $value; break; + case 'EREF': + $reference = $value; + break; + case 'TRTP': + $type = $value; + break; default: // Ignore the rest } } + + // Set a new description for the current transaction. If none was given + // set the description to type, name and reference + if ($newDescription) { + $this->data['description'] = $newDescription; + } else { + $this->data['description'] = sprintf('%s - %s (%s)', $type, $name, $reference); + } } return true; diff --git a/app/Helpers/Csv/Specifix/Dummy.php b/app/Helpers/Csv/Specifix/Dummy.php index 915e87bd37..2e4263a4d5 100644 --- a/app/Helpers/Csv/Specifix/Dummy.php +++ b/app/Helpers/Csv/Specifix/Dummy.php @@ -1,5 +1,5 @@ data = $data; } @@ -43,7 +43,7 @@ class Dummy extends Specifix implements SpecifixInterface /** * @param array $row */ - public function setRow($row) + public function setRow(array $row) { $this->row = $row; } diff --git a/app/Helpers/Csv/Specifix/RabobankDescription.php b/app/Helpers/Csv/Specifix/RabobankDescription.php index a8fced085a..249fc00cfe 100644 --- a/app/Helpers/Csv/Specifix/RabobankDescription.php +++ b/app/Helpers/Csv/Specifix/RabobankDescription.php @@ -1,5 +1,5 @@ data = $data; } @@ -48,7 +48,7 @@ class RabobankDescription extends Specifix implements SpecifixInterface /** * @param array $row */ - public function setRow($row) + public function setRow(array $row) { $this->row = $row; } diff --git a/app/Helpers/Csv/Specifix/Specifix.php b/app/Helpers/Csv/Specifix/Specifix.php index 2c2a191811..fa51625e8e 100644 --- a/app/Helpers/Csv/Specifix/Specifix.php +++ b/app/Helpers/Csv/Specifix/Specifix.php @@ -1,4 +1,5 @@ processorType = $processorType; diff --git a/app/Helpers/Csv/Specifix/SpecifixInterface.php b/app/Helpers/Csv/Specifix/SpecifixInterface.php index 34e9a3e833..b6534fbe51 100644 --- a/app/Helpers/Csv/Specifix/SpecifixInterface.php +++ b/app/Helpers/Csv/Specifix/SpecifixInterface.php @@ -1,4 +1,5 @@ getMap(); $options[$index] = $set; @@ -150,20 +153,21 @@ class Wizard implements WizardInterface } /** - * @param $path + * @param string $path * * @return string */ - public function storeCsvFile($path) + public function storeCsvFile(string $path) { $time = str_replace(' ', '-', microtime()); $fileName = 'csv-upload-' . Auth::user()->id . '-' . $time . '.csv.encrypted'; - $fullPath = storage_path('upload') . DIRECTORY_SEPARATOR . $fileName; - $content = file_get_contents($path); + $disk = Storage::disk('upload'); + $file = new SplFileObject($path, 'r'); + $content = $file->fread($file->getSize()); $contentEncrypted = Crypt::encrypt($content); - file_put_contents($fullPath, $contentEncrypted); + $disk->put($fileName, $contentEncrypted); - return $fullPath; + return $fileName; } @@ -188,7 +192,7 @@ class Wizard implements WizardInterface * * @return bool */ - protected function useRow($hasHeaders, $index) + protected function useRow(bool $hasHeaders, int $index) { return ($hasHeaders && $index > 1) || !$hasHeaders; } diff --git a/app/Helpers/Csv/WizardInterface.php b/app/Helpers/Csv/WizardInterface.php index 6257a85694..815a432a43 100644 --- a/app/Helpers/Csv/WizardInterface.php +++ b/app/Helpers/Csv/WizardInterface.php @@ -1,4 +1,5 @@ startOfFiscalYear($date); + if ($this->useCustomFiscalYear === true) { + // add 1 year and sub 1 day + $endDate->addYear(); + $endDate->subDay(); + } else { + $endDate->endOfYear(); + } + + + return $endDate; + } + /** * @param Carbon $date * @@ -52,27 +74,7 @@ class FiscalHelper implements FiscalHelperInterface } else { $startDate->startOfYear(); } + return $startDate; } - - /** - * @param Carbon $date - * - * @return Carbon date object - */ - public function endOfFiscalYear(Carbon $date) - { - // get start of fiscal year for passed date - $endDate = $this->startOfFiscalYear($date); - if ($this->useCustomFiscalYear === true) { - // add 1 year and sub 1 day - $endDate->addYear(); - $endDate->subDay(); - } else { - $endDate->endOfYear(); - } - - - return $endDate; - } } diff --git a/app/Helpers/FiscalHelperInterface.php b/app/Helpers/FiscalHelperInterface.php index f4ec6fba1a..b812fb9324 100644 --- a/app/Helpers/FiscalHelperInterface.php +++ b/app/Helpers/FiscalHelperInterface.php @@ -1,4 +1,5 @@ '
There is no help for this route!
', + 'text' => '' . strval(trans('firefly.route_has_no_help')) . '
', 'title' => $title, ]; - try { - $content['text'] = file_get_contents($uri); - } catch (ErrorException $e) { - Log::error(trim($e->getMessage())); + + Log::debug('Going to get from Github: ' . $uri); + + $result = Requests::get($uri); + + Log::debug('Status code was ' . $result->status_code . '.'); + + if ($result->status_code === 200) { + $content['text'] = $result->body; } + + if (strlen(trim($content['text'])) == 0) { - $content['text'] = 'There is no help for this route.
'; + Log::debug('No actual help text for this route (even though a page was found).'); + $content['text'] = '' . strval(trans('firefly.route_has_no_help')) . '
'; } $converter = new CommonMarkConverter(); $content['text'] = $converter->convertToHtml($content['text']); @@ -62,11 +70,11 @@ class Help implements HelpInterface /** * @codeCoverageIgnore * - * @param $route + * @param string $route * * @return bool */ - public function hasRoute($route) + public function hasRoute(string $route):bool { return Route::has($route); } @@ -74,11 +82,11 @@ class Help implements HelpInterface /** * @codeCoverageIgnore * - * @param $route + * @param string $route * * @return bool */ - public function inCache($route) + public function inCache(string $route):bool { return Cache::has('help.' . $route . '.title') && Cache::has('help.' . $route . '.text'); } @@ -86,12 +94,12 @@ class Help implements HelpInterface /** * @codeCoverageIgnore * - * @param $route - * @param array $content + * @param string $route + * @param array $content * * @internal param $title */ - public function putInCache($route, array $content) + public function putInCache(string $route, array $content) { Cache::put('help.' . $route . '.text', $content['text'], 10080); // a week. Cache::put('help.' . $route . '.title', $content['title'], 10080); diff --git a/app/Helpers/Help/HelpInterface.php b/app/Helpers/Help/HelpInterface.php index 3807c2c1ff..5f2c07b215 100644 --- a/app/Helpers/Help/HelpInterface.php +++ b/app/Helpers/Help/HelpInterface.php @@ -1,5 +1,5 @@ subDay(); - bcscale(2); // get balances for start. $startSet = Account::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id') @@ -53,7 +53,20 @@ class AccountReportHelper implements AccountReportHelperInterface ->whereNull('transactions.deleted_at') ->where('transaction_journals.date', '<=', $yesterday->format('Y-m-d')) ->groupBy('accounts.id') - ->get(['accounts.id', DB::Raw('SUM(`transactions`.`amount`) as `balance`')]); + ->get(['accounts.id', DB::raw('SUM(`transactions`.`amount`) as `balance`')]); + + // a special consideration for accounts that did exist on this exact day. + // we also grab the balance from today just in case, to see if that changes things. + // it's a fall back for users who (rightly so) start keeping score at the first of + // the month and find the first report lacking / broken. + $backupSet = Account::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id') + ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') + ->whereIn('accounts.id', $ids) + ->whereNull('transaction_journals.deleted_at') + ->whereNull('transactions.deleted_at') + ->where('transaction_journals.date', '<=', $start->format('Y-m-d')) + ->groupBy('accounts.id') + ->get(['accounts.id', DB::raw('SUM(`transactions`.`amount`) as `balance`')]); // and end: $endSet = Account::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id') @@ -63,24 +76,38 @@ class AccountReportHelper implements AccountReportHelperInterface ->whereNull('transactions.deleted_at') ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) ->groupBy('accounts.id') - ->get(['accounts.id', DB::Raw('SUM(`transactions`.`amount`) as `balance`')]); + ->get(['accounts.id', DB::raw('SUM(`transactions`.`amount`) as `balance`')]); $accounts->each( - function (Account $account) use ($startSet, $endSet) { + function (Account $account) use ($startSet, $endSet, $backupSet) { /** * The balance for today always incorporates transactions * made on today. So to get todays "start" balance, we sub one * day. */ // - $currentStart = $startSet->filter( + $account->startBalance = '0'; + $account->endBalance = '0'; + $currentStart = $startSet->filter( function (Account $entry) use ($account) { return $account->id == $entry->id; } ); + // grab entry from current backup as well: + $currentBackup = $backupSet->filter( + function (Account $entry) use ($account) { + return $account->id == $entry->id; + } + ); + + if ($currentStart->first()) { $account->startBalance = $currentStart->first()->balance; + } else { + if (is_null($currentStart->first()) && !is_null($currentBackup->first())) { + $account->startBalance = $currentBackup->first()->balance; + } } $currentEnd = $endSet->filter( diff --git a/app/Helpers/Report/AccountReportHelperInterface.php b/app/Helpers/Report/AccountReportHelperInterface.php index e52dea4498..bf9f650633 100644 --- a/app/Helpers/Report/AccountReportHelperInterface.php +++ b/app/Helpers/Report/AccountReportHelperInterface.php @@ -1,4 +1,5 @@ addBalanceLine($this->createEmptyBalanceLine($accounts, $spentData)); $balance->addBalanceLine($this->createTagsBalanceLine($accounts, $start, $end)); $balance->addBalanceLine($this->createDifferenceBalanceLine($accounts, $spentData, $start, $end)); - $balance->setBalanceHeader($header); return $balance; @@ -108,7 +108,7 @@ class BalanceReportHelper implements BalanceReportHelperInterface return $model->account_id == $account->id && $model->budget_id == $budget->id; } ); - $spent = 0; + $spent = '0'; if (!is_null($entry->first())) { $spent = $entry->first()->spent; } @@ -142,7 +142,7 @@ class BalanceReportHelper implements BalanceReportHelperInterface return $model->account_id == $account->id && is_null($model->budget_id); } ); - $spent = 0; + $spent = '0'; if (!is_null($entry->first())) { $spent = $entry->first()->spent; } @@ -151,11 +151,10 @@ class BalanceReportHelper implements BalanceReportHelperInterface return $tag->account_id == $account->id; } ); - $left = 0; + $left = '0'; if (!is_null($leftEntry->first())) { $left = $leftEntry->first()->sum; } - bcscale(2); $diffValue = bcadd($spent, $left); // difference: @@ -185,7 +184,7 @@ class BalanceReportHelper implements BalanceReportHelperInterface return $model->account_id == $account->id && is_null($model->budget_id); } ); - $spent = 0; + $spent = '0'; if (!is_null($entry->first())) { $spent = $entry->first()->spent; } @@ -221,11 +220,10 @@ class BalanceReportHelper implements BalanceReportHelperInterface return $tag->account_id == $account->id; } ); - $left = 0; + $left = '0'; if (!is_null($leftEntry->first())) { $left = $leftEntry->first()->sum; } - bcscale(2); // balanced by tags $tagEntry = new BalanceEntry; diff --git a/app/Helpers/Report/BalanceReportHelperInterface.php b/app/Helpers/Report/BalanceReportHelperInterface.php index fc0629b08e..4ef5d725b6 100644 --- a/app/Helpers/Report/BalanceReportHelperInterface.php +++ b/app/Helpers/Report/BalanceReportHelperInterface.php @@ -1,4 +1,5 @@ getBudgets(); $allRepetitions = $repository->getAllBudgetLimitRepetitions($start, $end); $allTotalSpent = $repository->spentAllPerDayForAccounts($accounts, $start, $end); - bcscale(2); foreach ($set as $budget) { @@ -48,16 +48,19 @@ class BudgetReportHelper implements BudgetReportHelperInterface return $rep->budget_id == $budget->id; } ); - $totalSpent = isset($allTotalSpent[$budget->id]) ? $allTotalSpent[$budget->id] : []; + $totalSpent = $allTotalSpent[$budget->id] ?? []; // no repetition(s) for this budget: if ($repetitions->count() == 0) { - $spent = array_sum($totalSpent); - $budgetLine = new BudgetLine; - $budgetLine->setBudget($budget); - $budgetLine->setOverspent($spent); - $object->addOverspent($spent); - $object->addBudgetLine($budgetLine); + + $spent = array_sum($totalSpent); + if ($spent > 0) { + $budgetLine = new BudgetLine; + $budgetLine->setBudget($budget); + $budgetLine->setOverspent($spent); + $object->addOverspent($spent); + $object->addBudgetLine($budgetLine); + } continue; } @@ -73,7 +76,7 @@ class BudgetReportHelper implements BudgetReportHelperInterface // 200 en -200 is 0, vergeleken met 0 === 0 // 200 en -300 is -100, vergeleken met 0 === -1 - $left = bccomp(bcadd($repetition->amount, $expenses), '0') === 1 ? bcadd($repetition->amount, $expenses) : 0; + $left = bccomp(bcadd($repetition->amount, $expenses), '0') === 1 ? bcadd($repetition->amount, $expenses) : '0'; $spent = bccomp(bcadd($repetition->amount, $expenses), '0') === 1 ? $expenses : '0'; $overspent = bccomp(bcadd($repetition->amount, $expenses), '0') === 1 ? '0' : bcadd($expenses, $repetition->amount); @@ -93,7 +96,7 @@ class BudgetReportHelper implements BudgetReportHelperInterface } // stuff outside of budgets: - $noBudget = $repository->getWithoutBudgetSum($start, $end); + $noBudget = $repository->getWithoutBudgetSum($accounts, $start, $end); $budgetLine = new BudgetLine; $budgetLine->setOverspent($noBudget); $budgetLine->setSpent($noBudget); @@ -115,7 +118,6 @@ class BudgetReportHelper implements BudgetReportHelperInterface */ protected function getSumOfRange(Carbon $start, Carbon $end, array $array) { - bcscale(2); $sum = '0'; $currentStart = clone $start; // to not mess with the original one $currentEnd = clone $end; // to not mess with the original one diff --git a/app/Helpers/Report/BudgetReportHelperInterface.php b/app/Helpers/Report/BudgetReportHelperInterface.php index 63b3a5a19f..69d479c3b0 100644 --- a/app/Helpers/Report/BudgetReportHelperInterface.php +++ b/app/Helpers/Report/BudgetReportHelperInterface.php @@ -1,4 +1,5 @@ setMax($bill->amount_max); // is hit in period? - bcscale(2); $entry = $journals->filter( function (TransactionJournal $journal) use ($bill) { - return $journal->bill_id == $bill->id; + return $journal->bill_id === $bill->id; } ); - if (!is_null($entry->first())) { - $billLine->setAmount($entry->first()->journalAmount); + $first = $entry->first(); + if (!is_null($first)) { + $billLine->setTransactionJournalId($first->id); + $billLine->setAmount($first->journalAmount); $billLine->setHit(true); } else { $billLine->setHit(false); } - - $collection->addBill($billLine); + if (!(!$billLine->isHit() && !$billLine->isActive())) { + $collection->addBill($billLine); + } } @@ -130,7 +134,7 @@ class ReportHelper implements ReportHelperInterface * * @return Expense */ - public function getExpenseReport($start, $end, Collection $accounts) + public function getExpenseReport(Carbon $start, Carbon $end, Collection $accounts) { $object = new Expense; $set = $this->query->expense($accounts, $start, $end); @@ -152,7 +156,7 @@ class ReportHelper implements ReportHelperInterface * * @return Income */ - public function getIncomeReport($start, $end, Collection $accounts) + public function getIncomeReport(Carbon $start, Carbon $end, Collection $accounts) { $object = new Income; $set = $this->query->income($accounts, $start, $end); @@ -213,6 +217,64 @@ class ReportHelper implements ReportHelperInterface return $months; } + /** + * Returns an array of tags and their comparitive size with amounts bla bla. + * + * @param Carbon $start + * @param Carbon $end + * @param Collection $accounts + * + * @return array + */ + public function tagReport(Carbon $start, Carbon $end, Collection $accounts): array + { + $ids = $accounts->pluck('id')->toArray(); + $set = Tag:: + distinct() + ->leftJoin('tag_transaction_journal', 'tags.id', '=', 'tag_transaction_journal.tag_id') + ->leftJoin('transaction_journals', 'tag_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') + ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') + ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) + ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) + ->whereIn('transactions.account_id', $ids)->get( + ['tags.id', 'tags.tag', 'transaction_journals.id as journal_id', 'transactions.amount'] + ); + $collection = []; + if ($set->count() === 0) { + return $collection; + } + foreach ($set as $entry) { + // less than zero? multiply to be above zero. + $amount = $entry->amount; + if (bccomp($amount, '0', 2) === -1) { + $amount = bcmul($amount, '-1'); + } + $id = intval($entry->id); + + if (!isset($collection[$id])) { + $collection[$id] = [ + 'id' => $id, + 'tag' => $entry->tag, + 'amount' => $amount, + ]; + } else { + $collection[$id]['amount'] = bcadd($collection[$id]['amount'], $amount); + } + } + + // cleanup collection (match "fonts") + $max = strval(max(array_column($collection, 'amount'))); + foreach ($collection as $id => $entry) { + $size = bcdiv($entry['amount'], $max, 4); + if (bccomp($size, '0.25') === -1) { + $size = '0.5'; + } + $collection[$id]['fontsize'] = $size; + } + + return $collection; + } + /** * Take the array as returned by SingleCategoryRepositoryInterface::spentPerDay and SingleCategoryRepositoryInterface::earnedByDay * and sum up everything in the array in the given range. @@ -225,7 +287,6 @@ class ReportHelper implements ReportHelperInterface */ protected function getSumOfRange(Carbon $start, Carbon $end, array $array) { - bcscale(2); $sum = '0'; $currentStart = clone $start; // to not mess with the original one $currentEnd = clone $end; // to not mess with the original one diff --git a/app/Helpers/Report/ReportHelperInterface.php b/app/Helpers/Report/ReportHelperInterface.php index 7a1833a230..e45fd3b56f 100644 --- a/app/Helpers/Report/ReportHelperInterface.php +++ b/app/Helpers/Report/ReportHelperInterface.php @@ -1,4 +1,5 @@ groupBy('dateFormatted') ->get( [ - DB::Raw('DATE_FORMAT(`transaction_journals`.`date`,"%Y-%m") AS `dateFormatted`'), - DB::Raw('SUM(`t_to`.`amount`) AS `sum`'), + DB::raw('DATE_FORMAT(`transaction_journals`.`date`,"%Y-%m") AS `dateFormatted`'), + DB::raw('SUM(`t_to`.`amount`) AS `sum`'), ] ); $array = []; @@ -86,7 +87,7 @@ class ReportQuery implements ReportQueryInterface } ) ->leftJoin('accounts', 't_to.account_id', '=', 'accounts.id') - ->transactionTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE]) + ->transactionTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER]) ->before($end) ->after($start) ->whereIn('t_from.account_id', $ids) @@ -121,7 +122,7 @@ class ReportQuery implements ReportQueryInterface } ) ->leftJoin('accounts', 't_from.account_id', '=', 'accounts.id') - ->transactionTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE]) + ->transactionTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER]) ->before($end) ->after($start) ->whereIn('t_to.account_id', $ids) @@ -163,8 +164,8 @@ class ReportQuery implements ReportQueryInterface ->groupBy('dateFormatted') ->get( [ - DB::Raw('DATE_FORMAT(`transaction_journals`.`date`,"%Y-%m") AS `dateFormatted`'), - DB::Raw('SUM(`t_from`.`amount`) AS `sum`'), + DB::raw('DATE_FORMAT(`transaction_journals`.`date`,"%Y-%m") AS `dateFormatted`'), + DB::raw('SUM(`t_from`.`amount`) AS `sum`'), ] ); $array = []; diff --git a/app/Helpers/Report/ReportQueryInterface.php b/app/Helpers/Report/ReportQueryInterface.php index 0656ec2115..db1efc6d5a 100644 --- a/app/Helpers/Report/ReportQueryInterface.php +++ b/app/Helpers/Report/ReportQueryInterface.php @@ -1,4 +1,5 @@ accountType->type); $subTitle = trans('firefly.delete_' . $typeName . '_account', ['name' => $account->name]); - $accountList = Expandedform::makeSelectList($repository->getAccounts([$account->accountType->type]), true); + $accountList = ExpandedForm::makeSelectList($repository->getAccounts([$account->accountType->type]), true); unset($accountList[$account->id]); // put previous url in session @@ -87,14 +87,14 @@ class AccountController extends Controller $type = $account->accountType->type; $typeName = Config::get('firefly.shortNamesByFullName.' . $type); $name = $account->name; - $moveTo = Auth::user()->accounts()->find(intval(Input::get('move_account_before_delete'))); + $moveTo = $repository->find(intval(Input::get('move_account_before_delete'))); $repository->destroy($account, $moveTo); Session::flash('success', trans('firefly.' . $typeName . '_deleted', ['name' => $name])); Preferences::mark(); - return redirect(Session::get('accounts.delete.url')); + return redirect(session('accounts.delete.url')); } /** @@ -112,7 +112,7 @@ class AccountController extends Controller $openingBalance = $repository->openingBalanceTransaction($account); // put previous url in session if not redirect from store (not "return_to_edit"). - if (Session::get('accounts.edit.fromUpdate') !== true) { + if (session('accounts.edit.fromUpdate') !== true) { Session::put('accounts.edit.url', URL::previous()); } Session::forget('accounts.edit.fromUpdate'); @@ -122,16 +122,17 @@ class AccountController extends Controller // the opening balance is tricky: $openingBalanceAmount = null; - if ($openingBalance) { + if ($openingBalance->id) { $transaction = $repository->getFirstTransaction($openingBalance, $account); $openingBalanceAmount = $transaction->amount; } $preFilled = [ + 'accountNumber' => $account->getMeta('accountNumber'), 'accountRole' => $account->getMeta('accountRole'), 'ccType' => $account->getMeta('ccType'), 'ccMonthlyPaymentDate' => $account->getMeta('ccMonthlyPaymentDate'), - 'openingBalanceDate' => $openingBalance ? $openingBalance->date->format('Y-m-d') : null, + 'openingBalanceDate' => $openingBalance->id ? $openingBalance->date->format('Y-m-d') : null, 'openingBalance' => $openingBalanceAmount, 'virtualBalance' => round($account->virtual_balance, 2), ]; @@ -148,14 +149,18 @@ class AccountController extends Controller * * @return \Illuminate\View\View */ - public function index(ARI $repository, $what) + public function index(ARI $repository, string $what) { + $what = $what ?? 'asset'; + $subTitle = trans('firefly.' . $what . '_accounts'); $subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what); $types = Config::get('firefly.accountTypesByIdentifier.' . $what); $accounts = $repository->getAccounts($types); - $start = clone Session::get('start', Carbon::now()->startOfMonth()); - $end = clone Session::get('end', Carbon::now()->endOfMonth()); + /** @var Carbon $start */ + $start = clone session('start', Carbon::now()->startOfMonth()); + /** @var Carbon $end */ + $end = clone session('end', Carbon::now()->endOfMonth()); $start->subDay(); $ids = $accounts->pluck('id')->toArray(); @@ -209,6 +214,7 @@ class AccountController extends Controller 'active' => true, 'user' => Auth::user()->id, 'iban' => $request->input('iban'), + 'accountNumber' => $request->input('accountNumber'), 'accountRole' => $request->input('accountRole'), 'openingBalance' => round($request->input('openingBalance'), 2), 'openingBalanceDate' => new Carbon((string)$request->input('openingBalanceDate')), @@ -221,6 +227,13 @@ class AccountController extends Controller Session::flash('success', 'New account "' . $account->name . '" stored!'); Preferences::mark(); + // update preferences if necessary: + $frontPage = Preferences::get('frontPageAccounts', [])->data; + if (count($frontPage) > 0) { + $frontPage[] = $account->id; + Preferences::set('frontPageAccounts', $frontPage); + } + if (intval(Input::get('create_another')) === 1) { // set value so create routine will not overwrite URL: Session::put('accounts.create.fromStore', true); @@ -229,7 +242,7 @@ class AccountController extends Controller } // redirect to previous URL. - return redirect(Session::get('accounts.create.url')); + return redirect(session('accounts.create.url')); } /** @@ -247,6 +260,7 @@ class AccountController extends Controller 'active' => $request->input('active'), 'user' => Auth::user()->id, 'iban' => $request->input('iban'), + 'accountNumber' => $request->input('accountNumber'), 'accountRole' => $request->input('accountRole'), 'virtualBalance' => round($request->input('virtualBalance'), 2), 'openingBalance' => round($request->input('openingBalance'), 2), @@ -268,24 +282,24 @@ class AccountController extends Controller } // redirect to previous URL. - return redirect(Session::get('accounts.edit.url')); + return redirect(session('accounts.edit.url')); } /** * @param array $array - * @param $entryId + * @param int $entryId * * @return null|mixed */ - protected function isInArray(array $array, $entryId) + protected function isInArray(array $array, int $entryId) { if (isset($array[$entryId])) { return $array[$entryId]; } - return null; + return ''; } } diff --git a/app/Http/Controllers/AttachmentController.php b/app/Http/Controllers/AttachmentController.php index 0e818f3f20..c380af181f 100644 --- a/app/Http/Controllers/AttachmentController.php +++ b/app/Http/Controllers/AttachmentController.php @@ -1,10 +1,11 @@ $name])); Preferences::mark(); - return redirect(Session::get('attachments.delete.url')); + return redirect(session('attachments.delete.url')); } /** - * @param Attachment $attachment - * @param AttachmentHelperInterface $helper + * @param Attachment $attachment + * + * @throws FireflyException * - * @return string */ - public function download(Attachment $attachment, AttachmentHelperInterface $helper) + public function download(Attachment $attachment) { + // create a disk. + $disk = Storage::disk('upload'); + $file = $attachment->fileName(); - $file = $helper->getAttachmentLocation($attachment); - if (file_exists($file)) { + if ($disk->exists($file)) { $quoted = sprintf('"%s"', addcslashes(basename($attachment->filename), '"\\')); - return response(Crypt::decrypt(file_get_contents($file)), 200) + return response(Crypt::decrypt($disk->get($file)), 200) ->header('Content-Description', 'File Transfer') ->header('Content-Type', 'application/octet-stream') ->header('Content-Disposition', 'attachment; filename=' . $quoted) @@ -92,11 +96,10 @@ class AttachmentController extends Controller ->header('Expires', '0') ->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0') ->header('Pragma', 'public') - ->header('Content-Length', $attachment->size); + ->header('Content-Length', $disk->size($file)); - } else { - abort(404); } + throw new FireflyException('Could not find the indicated attachment. The file is no longer there.'); } /** @@ -110,7 +113,7 @@ class AttachmentController extends Controller $subTitle = trans('firefly.edit_attachment', ['name' => $attachment->filename]); // put previous url in session if not redirect from store (not "return_to_edit"). - if (Session::get('attachments.edit.fromUpdate') !== true) { + if (session('attachments.edit.fromUpdate') !== true) { Session::put('attachments.edit.url', URL::previous()); } Session::forget('attachments.edit.fromUpdate'); @@ -167,7 +170,7 @@ class AttachmentController extends Controller } // redirect to previous URL. - return redirect(Session::get('attachments.edit.url')); + return redirect(session('attachments.edit.url')); } diff --git a/app/Http/Controllers/Auth/AuthController.php b/app/Http/Controllers/Auth/AuthController.php index 79c24d30c2..0d82af7b2c 100644 --- a/app/Http/Controllers/Auth/AuthController.php +++ b/app/Http/Controllers/Auth/AuthController.php @@ -1,10 +1,12 @@ getGuard())->attempt($credentials, $request->has('remember'))) { - return $this->handleUserWasAuthenticated($request, $throttles); } // check if user is blocked: - $message = ''; + $errorMessage = ''; /** @var User $foundUser */ $foundUser = User::where('email', $credentials['email'])->where('blocked', 1)->first(); if (!is_null($foundUser)) { // if it exists, show message: - $code = $foundUser->blocked_code; - - if (strlen($code) == 0) { - $code = 'general_blocked'; - } - $message = trans('firefly.' . $code . '_error', ['email' => $credentials['email']]); + $code = strlen(strval($foundUser->blocked_code)) > 0 ? $foundUser->blocked_code : 'general_blocked'; + $errorMessage = strval(trans('firefly.' . $code . '_error', ['email' => $credentials['email']])); + $this->reportBlockedUserLoginAttempt($foundUser, $code, $request->ip()); } if ($throttles) { $this->incrementLoginAttempts($request); } - return $this->sendFailedLoginResponse($request, $message); + return $this->sendFailedLoginResponse($request, $errorMessage); } /** * Handle a registration request for the application. * + * @param UserRepositoryInterface $repository * @param \Illuminate\Http\Request $request * * @return \Illuminate\Http\Response + * @throws FireflyException + * @throws \Illuminate\Foundation\Validation\ValidationException */ - public function register(Request $request) + public function register(UserRepositoryInterface $repository, Request $request) { $validator = $this->validator($request->all()); @@ -112,6 +114,9 @@ class AuthController extends Controller // is user email domain blocked? if ($this->isBlockedDomain($data['email'])) { $validator->getMessageBag()->add('email', (string)trans('validation.invalid_domain')); + + $this->reportBlockedDomainRegistrationAttempt($data['email'], $request->ip()); + $this->throwValidationException( $request, $validator ); @@ -132,7 +137,7 @@ class AuthController extends Controller $message->to($email, $email)->subject('Welcome to Firefly III! '); } ); - } catch (\Swift_TransportException $e) { + } catch (Swift_TransportException $e) { Log::error($e->getMessage()); } @@ -142,19 +147,13 @@ class AuthController extends Controller Session::flash('gaEventAction', 'new-registration'); // first user ever? - if (User::count() == 1) { - $admin = Role::where('name', 'owner')->first(); - Auth::user()->attachRole($admin); + if ($repository->count() == 1) { + $repository->attachRole(Auth::user(), 'owner'); } - return redirect($this->redirectPath()); } - // @codeCoverageIgnoreStart - abort(500, 'Not a user!'); - - - return redirect($this->redirectPath()); + throw new FireflyException('The authenticated user object is invalid.'); } /** @@ -206,11 +205,11 @@ class AuthController extends Controller /** * Get the failed login message. * - * @param $message + * @param string $message * * @return string */ - protected function getFailedLoginMessage($message) + protected function getFailedLoginMessage(string $message) { if (strlen($message) > 0) { return $message; @@ -222,11 +221,11 @@ class AuthController extends Controller } /** - * @param $email + * @param string $email * * @return bool */ - protected function isBlockedDomain($email) + protected function isBlockedDomain(string $email) { $parts = explode('@', $email); $blocked = $this->getBlockedDomains(); @@ -242,12 +241,11 @@ class AuthController extends Controller * Get the failed login response instance. * * @param \Illuminate\Http\Request $request - * - * @param $message + * @param string $message * * @return \Illuminate\Http\Response */ - protected function sendFailedLoginResponse(Request $request, $message) + protected function sendFailedLoginResponse(Request $request, string $message) { return redirect()->back() ->withInput($request->only($this->loginUsername(), 'remember')) @@ -274,4 +272,62 @@ class AuthController extends Controller ] ); } + + /** + * Send a message home about a blocked domain and the address attempted to register. + * + * @param string $registrationMail + * @param string $ipAddress + */ + private function reportBlockedDomainRegistrationAttempt(string $registrationMail, string $ipAddress) + { + try { + $email = env('SITE_OWNER', false); + $parts = explode('@', $registrationMail); + $domain = $parts[1]; + $fields = [ + 'email_address' => $registrationMail, + 'blocked_domain' => $domain, + 'ip' => $ipAddress, + ]; + + Mail::send( + ['emails.blocked-registration-html', 'emails.blocked-registration'], $fields, function (Message $message) use ($email, $domain) { + $message->to($email, $email)->subject('Blocked a registration attempt with domain ' . $domain . '.'); + } + ); + } catch (Swift_TransportException $e) { + Log::error($e->getMessage()); + } + } + + /** + * Send a message home about the blocked attempt to login. + * Perhaps in a later stage, simply log these messages. + * + * @param User $user + * @param string $code + * @param string $ipAddress + */ + private function reportBlockedUserLoginAttempt(User $user, string $code, string $ipAddress) + { + + try { + $email = env('SITE_OWNER', false); + $fields = [ + 'user_id' => $user->id, + 'user_address' => $user->email, + 'code' => $code, + 'ip' => $ipAddress, + ]; + + Mail::send( + ['emails.blocked-login-html', 'emails.blocked-login'], $fields, function (Message $message) use ($email, $user) { + $message->to($email, $email)->subject('Blocked a login attempt from ' . trim($user->email) . '.'); + } + ); + } catch (Swift_TransportException $e) { + Log::error($e->getMessage()); + } + } } diff --git a/app/Http/Controllers/Auth/PasswordController.php b/app/Http/Controllers/Auth/PasswordController.php index 855cfb5924..e341c46372 100644 --- a/app/Http/Controllers/Auth/PasswordController.php +++ b/app/Http/Controllers/Auth/PasswordController.php @@ -1,4 +1,5 @@ data; + + if (strlen($secret) === 0) { + throw new FireflyException('Your two factor authentication secret is empty, which it should be at this point. Please check the log files.'); + } + Session::flash('two-factor-secret', $secret); + + return view('auth.two-factor', compact('user')); + } + + /** + * @return mixed + * @throws FireflyException + */ + public function lostTwoFactor() + { + $user = Auth::user(); + $siteOwner = env('SITE_OWNER', ''); + + Log::info( + 'To reset the two factor authentication for user #' . $user->id . + ' (' . $user->email . '), simply open the "preferences" table and delete the entries with the names "twoFactorAuthEnabled" and' . + ' "twoFactorAuthSecret" for user_id ' . $user->id . '. That will take care of it.' + ); + + return view('auth.lost-two-factor', compact('user', 'siteOwner')); + } + + /** + * @param TokenFormRequest $request + * + * @return mixed + */ + public function postIndex(TokenFormRequest $request) + { + Session::put('twofactor-authenticated', true); + Session::put('twofactor-authenticated-date', new Carbon); + + return redirect(route('home')); + } + +} \ No newline at end of file diff --git a/app/Http/Controllers/BillController.php b/app/Http/Controllers/BillController.php index ca59f0d256..e74da3c093 100644 --- a/app/Http/Controllers/BillController.php +++ b/app/Http/Controllers/BillController.php @@ -20,7 +20,7 @@ class BillController extends Controller { /** - * @codeCoverageIgnore + * */ public function __construct() { @@ -39,7 +39,7 @@ class BillController extends Controller // put previous url in session if not redirect from store (not "create another"). - if (Session::get('bills.create.fromStore') !== true) { + if (session('bills.create.fromStore') !== true) { Session::put('bills.create.url', URL::previous()); } Session::forget('bills.create.fromStore'); @@ -78,7 +78,7 @@ class BillController extends Controller Session::flash('success', 'The bill was deleted.'); Preferences::mark(); - return redirect(Session::get('bills.delete.url')); + return redirect(session('bills.delete.url')); } /** @@ -92,7 +92,7 @@ class BillController extends Controller $subTitle = trans('firefly.edit_bill', ['name' => $bill->name]); // put previous url in session if not redirect from store (not "return_to_edit"). - if (Session::get('bills.edit.fromUpdate') !== true) { + if (session('bills.edit.fromUpdate') !== true) { Session::put('bills.edit.url', URL::previous()); } Session::forget('bills.edit.fromUpdate'); @@ -184,7 +184,7 @@ class BillController extends Controller } // redirect to previous URL. - return redirect(Session::get('bills.create.url')); + return redirect(session('bills.create.url')); } @@ -211,7 +211,7 @@ class BillController extends Controller } // redirect to previous URL. - return redirect(Session::get('bills.edit.url')); + return redirect(session('bills.edit.url')); } diff --git a/app/Http/Controllers/BudgetController.php b/app/Http/Controllers/BudgetController.php index e86d95bb46..6424acf265 100644 --- a/app/Http/Controllers/BudgetController.php +++ b/app/Http/Controllers/BudgetController.php @@ -3,6 +3,7 @@ use Amount; use Auth; use Carbon\Carbon; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Http\Requests\BudgetFormRequest; use FireflyIII\Models\Budget; use FireflyIII\Models\LimitRepetition; @@ -26,7 +27,7 @@ class BudgetController extends Controller { /** - * @codeCoverageIgnore + * */ public function __construct() { @@ -44,8 +45,9 @@ class BudgetController extends Controller */ public function amount(BudgetRepositoryInterface $repository, Budget $budget) { - $amount = intval(Input::get('amount')); - $date = Session::get('start', Carbon::now()->startOfMonth()); + $amount = intval(Input::get('amount')); + /** @var Carbon $date */ + $date = session('start', Carbon::now()->startOfMonth()); $limitRepetition = $repository->updateLimitAmount($budget, $date, $amount); if ($amount == 0) { $limitRepetition = null; @@ -62,7 +64,7 @@ class BudgetController extends Controller public function create() { // put previous url in session if not redirect from store (not "create another"). - if (Session::get('budgets.create.fromStore') !== true) { + if (session('budgets.create.fromStore') !== true) { Session::put('budgets.create.url', URL::previous()); } Session::forget('budgets.create.fromStore'); @@ -107,7 +109,7 @@ class BudgetController extends Controller Preferences::mark(); - return redirect(Session::get('budgets.delete.url')); + return redirect(session('budgets.delete.url')); } /** @@ -120,7 +122,7 @@ class BudgetController extends Controller $subTitle = trans('firefly.edit_budget', ['name' => $budget->name]); // put previous url in session if not redirect from store (not "return_to_edit"). - if (Session::get('budgets.edit.fromUpdate') !== true) { + if (session('budgets.edit.fromUpdate') !== true) { Session::put('budgets.edit.url', URL::previous()); } Session::forget('budgets.edit.fromUpdate'); @@ -140,19 +142,20 @@ class BudgetController extends Controller */ public function index(BudgetRepositoryInterface $repository, ARI $accountRepository) { - $budgets = $repository->getActiveBudgets(); - $inactive = $repository->getInactiveBudgets(); - $spent = '0'; - $budgeted = '0'; - $range = Preferences::get('viewRange', '1M')->data; - $start = Navigation::startOfPeriod(Session::get('start', new Carbon), $range); + $budgets = $repository->getActiveBudgets(); + $inactive = $repository->getInactiveBudgets(); + $spent = '0'; + $budgeted = '0'; + $range = Preferences::get('viewRange', '1M')->data; + /** @var Carbon $date */ + $date = session('start', new Carbon); + $start = Navigation::startOfPeriod($date, $range); $end = Navigation::endOfPeriod($start, $range); $key = 'budgetIncomeTotal' . $start->format('Ymd') . $end->format('Ymd'); $budgetIncomeTotal = Preferences::get($key, 1000)->data; $period = Navigation::periodShow($start, $range); $accounts = $accountRepository->getAccounts(['Default account', 'Asset account', 'Cash account']); - bcscale(2); /** * Do some cleanup: */ @@ -186,9 +189,11 @@ class BudgetController extends Controller */ public function noBudget(BudgetRepositoryInterface $repository) { - $range = Preferences::get('viewRange', '1M')->data; - $start = Navigation::startOfPeriod(Session::get('start', new Carbon), $range); - $end = Navigation::endOfPeriod($start, $range); + /** @var Carbon $start */ + $start = session('start', Carbon::now()->startOfMonth()); + /** @var Carbon $end */ + $end = session('end', Carbon::now()->endOfMonth()); + $list = $repository->getWithoutBudget($start, $end); $subTitle = trans( 'firefly.without_budget_between', @@ -204,7 +209,9 @@ class BudgetController extends Controller public function postUpdateIncome() { $range = Preferences::get('viewRange', '1M')->data; - $start = Navigation::startOfPeriod(Session::get('start', new Carbon), $range); + /** @var Carbon $date */ + $date = session('start', new Carbon); + $start = Navigation::startOfPeriod($date, $range); $end = Navigation::endOfPeriod($start, $range); $key = 'budgetIncomeTotal' . $start->format('Ymd') . $end->format('Ymd'); @@ -217,19 +224,18 @@ class BudgetController extends Controller /** * @param BudgetRepositoryInterface $repository * @param Budget $budget - * @param LimitRepetition $repetition + * @param LimitRepetition|null $repetition * - * @return \Illuminate\View\View + * @return View + * @throws FireflyException */ public function show(BudgetRepositoryInterface $repository, Budget $budget, LimitRepetition $repetition = null) { if (!is_null($repetition->id) && $repetition->budgetLimit->budget->id != $budget->id) { - $message = 'Invalid selection.'; - - return view('error', compact('message')); + throw new FireflyException('This budget limit is not part of this budget.'); } - $journals = $repository->getJournals($budget, $repetition); + $journals = $repository->getJournals($budget, $repetition, 50); if (is_null($repetition->id)) { $start = $repository->firstActivity($budget); @@ -282,7 +288,7 @@ class BudgetController extends Controller } // redirect to previous URL. - return redirect(Session::get('budgets.create.url')); + return redirect(session('budgets.create.url')); } @@ -313,7 +319,7 @@ class BudgetController extends Controller } // redirect to previous URL. - return redirect(Session::get('budgets.edit.url')); + return redirect(session('budgets.edit.url')); } @@ -322,8 +328,11 @@ class BudgetController extends Controller */ public function updateIncome() { - $range = Preferences::get('viewRange', '1M')->data; - $start = Navigation::startOfPeriod(Session::get('start', new Carbon), $range); + $range = Preferences::get('viewRange', '1M')->data; + + /** @var Carbon $date */ + $date = session('start', new Carbon); + $start = Navigation::startOfPeriod($date, $range); $end = Navigation::endOfPeriod($start, $range); $key = 'budgetIncomeTotal' . $start->format('Ymd') . $end->format('Ymd'); $amount = Preferences::get($key, 1000); diff --git a/app/Http/Controllers/CategoryController.php b/app/Http/Controllers/CategoryController.php index 1b59519808..f7239b898b 100644 --- a/app/Http/Controllers/CategoryController.php +++ b/app/Http/Controllers/CategoryController.php @@ -25,7 +25,7 @@ class CategoryController extends Controller { /** - * @codeCoverageIgnore + * */ public function __construct() { @@ -40,7 +40,7 @@ class CategoryController extends Controller public function create() { // put previous url in session if not redirect from store (not "create another"). - if (Session::get('categories.create.fromStore') !== true) { + if (session('categories.create.fromStore') !== true) { Session::put('categories.create.url', URL::previous()); } Session::forget('categories.create.fromStore'); @@ -83,7 +83,7 @@ class CategoryController extends Controller Session::flash('success', 'The category "' . e($name) . '" was deleted.'); Preferences::mark(); - return redirect(Session::get('categories.delete.url')); + return redirect(session('categories.delete.url')); } /** @@ -96,7 +96,7 @@ class CategoryController extends Controller $subTitle = trans('firefly.edit_category', ['name' => $category->name]); // put previous url in session if not redirect from store (not "return_to_edit"). - if (Session::get('categories.edit.fromUpdate') !== true) { + if (session('categories.edit.fromUpdate') !== true) { Session::put('categories.edit.url', URL::previous()); } Session::forget('categories.edit.fromUpdate'); @@ -133,8 +133,10 @@ class CategoryController extends Controller */ public function noCategory(CRI $repository) { - $start = Session::get('start', Carbon::now()->startOfMonth()); - $end = Session::get('end', Carbon::now()->startOfMonth()); + /** @var Carbon $start */ + $start = session('start', Carbon::now()->startOfMonth()); + /** @var Carbon $end */ + $end = session('end', Carbon::now()->startOfMonth()); $list = $repository->listNoCategory($start, $end); $subTitle = trans( 'firefly.without_category_between', @@ -213,7 +215,7 @@ class CategoryController extends Controller * * @return \Illuminate\View\View */ - public function showWithDate(SCRI $repository, Category $category, $date) + public function showWithDate(SCRI $repository, Category $category, string $date) { $carbon = new Carbon($date); $range = Preferences::get('viewRange', '1M')->data; @@ -284,7 +286,7 @@ class CategoryController extends Controller } // redirect to previous URL. - return redirect(Session::get('categories.edit.url')); + return redirect(session('categories.edit.url')); } diff --git a/app/Http/Controllers/Chart/AccountController.php b/app/Http/Controllers/Chart/AccountController.php index 1110abaa27..4f0c5d365a 100644 --- a/app/Http/Controllers/Chart/AccountController.php +++ b/app/Http/Controllers/Chart/AccountController.php @@ -1,4 +1,5 @@ startOfMonth()); - $end = clone Session::get('end', Carbon::now()->endOfMonth()); + $start = clone session('start', Carbon::now()->startOfMonth()); + $end = clone session('end', Carbon::now()->endOfMonth()); $accounts = $repository->getAccounts(['Expense account', 'Beneficiary account']); // chart properties for cache: @@ -106,8 +106,8 @@ class AccountController extends Controller public function frontpage(ARI $repository) { $frontPage = Preferences::get('frontPageAccounts', []); - $start = clone Session::get('start', Carbon::now()->startOfMonth()); - $end = clone Session::get('end', Carbon::now()->endOfMonth()); + $start = clone session('start', Carbon::now()->startOfMonth()); + $end = clone session('end', Carbon::now()->endOfMonth()); $accounts = $repository->getFrontpageAccounts($frontPage); // chart properties for cache: @@ -138,8 +138,8 @@ class AccountController extends Controller { - $start = Session::get('start', Carbon::now()->startOfMonth()); - $end = Session::get('end', Carbon::now()->endOfMonth()); + $start = session('start', Carbon::now()->startOfMonth()); + $end = session('end', Carbon::now()->endOfMonth()); // chart properties for cache: $cache = new CacheProperties(); diff --git a/app/Http/Controllers/Chart/BillController.php b/app/Http/Controllers/Chart/BillController.php index d1e58998c5..aba1965f05 100644 --- a/app/Http/Controllers/Chart/BillController.php +++ b/app/Http/Controllers/Chart/BillController.php @@ -1,4 +1,5 @@ startOfMonth()); - $end = Session::get('end', Carbon::now()->endOfMonth()); + $start = session('start', Carbon::now()->startOfMonth()); + $end = session('end', Carbon::now()->endOfMonth()); $paid = $repository->getBillsPaidInRange($start, $end); // will be a negative amount. $unpaid = $repository->getBillsUnpaidInRange($start, $end); // will be a positive amount. $creditCardDue = $repository->getCreditCardBill($start, $end); diff --git a/app/Http/Controllers/Chart/BudgetController.php b/app/Http/Controllers/Chart/BudgetController.php index 848a13179b..18a61759d2 100644 --- a/app/Http/Controllers/Chart/BudgetController.php +++ b/app/Http/Controllers/Chart/BudgetController.php @@ -1,4 +1,5 @@ generator = app('FireflyIII\Generator\Chart\Budget\BudgetChartGeneratorInterface'); } + /** + * @param BudgetRepositoryInterface $repository + * @param Budget $budget + * + * @return \Symfony\Component\HttpFoundation\Response + */ + public function budget(BudgetRepositoryInterface $repository, Budget $budget) + { + + // dates and times + $first = $repository->getFirstBudgetLimitDate($budget); + $range = Preferences::get('viewRange', '1M')->data; + $last = session('end', new Carbon); + + // chart properties for cache: + $cache = new CacheProperties(); + $cache->addProperty($first); + $cache->addProperty($last); + $cache->addProperty('budget'); + if ($cache->has()) { + + return Response::json($cache->get()); // @codeCoverageIgnore + } + + $final = clone $last; + $final->addYears(2); + $last = Navigation::endOfX($last, $range, $final); + $entries = new Collection; + // get all expenses: + $spentArray = $repository->spentPerDay($budget, $first, $last); + + while ($first < $last) { + + // periodspecific dates: + $currentStart = Navigation::startOfPeriod($first, $range); + $currentEnd = Navigation::endOfPeriod($first, $range); + $spent = $this->getSumOfRange($currentStart, $currentEnd, $spentArray); + $entry = [$first, ($spent * -1)]; + + $entries->push($entry); + $first = Navigation::addPeriod($first, $range, 0); + } + + $data = $this->generator->budget($entries); + $cache->store($data); + + return Response::json($data); + } + + /** + * Shows the amount left in a specific budget limit. + * + * @param BudgetRepositoryInterface $repository + * @param Budget $budget + * @param LimitRepetition $repetition + * + * @return \Symfony\Component\HttpFoundation\Response + */ + public function budgetLimit(BudgetRepositoryInterface $repository, Budget $budget, LimitRepetition $repetition) + { + $start = clone $repetition->startdate; + $end = $repetition->enddate; + + // chart properties for cache: + $cache = new CacheProperties(); + $cache->addProperty($start); + $cache->addProperty($end); + $cache->addProperty('budget'); + $cache->addProperty('limit'); + $cache->addProperty($budget->id); + $cache->addProperty($repetition->id); + if ($cache->has()) { + return Response::json($cache->get()); // @codeCoverageIgnore + } + + $set = $repository->getExpensesPerDay($budget, $start, $end); + $entries = new Collection; + $amount = $repetition->amount; + + // get sum (har har)! + while ($start <= $end) { + $formatted = $start->format('Y-m-d'); + $filtered = $set->filter( + function (Budget $obj) use ($formatted) { + return $obj->date == $formatted; + } + ); + $sum = is_null($filtered->first()) ? '0' : $filtered->first()->dailyAmount; + + /* + * Sum of expenses on this day: + */ + $amount = round(bcadd(strval($amount), $sum), 2); + $entries->push([clone $start, $amount]); + $start->addDay(); + } + + $data = $this->generator->budgetLimit($entries); + $cache->store($data); + + return Response::json($data); + + } + + /** + * Shows a budget list with spent/left/overspent. + * + * @param BudgetRepositoryInterface $repository + * + * @param ARI $accountRepository + * + * @return \Symfony\Component\HttpFoundation\Response + */ + public function frontpage(BudgetRepositoryInterface $repository, ARI $accountRepository) + { + $start = session('start', Carbon::now()->startOfMonth()); + $end = session('end', Carbon::now()->endOfMonth()); + + // chart properties for cache: + $cache = new CacheProperties(); + $cache->addProperty($start); + $cache->addProperty($end); + $cache->addProperty('budget'); + $cache->addProperty('all'); + if ($cache->has()) { + return Response::json($cache->get()); // @codeCoverageIgnore + } + + $budgets = $repository->getBudgetsAndLimitsInRange($start, $end); + $allEntries = new Collection; + $accounts = $accountRepository->getAccounts(['Default account', 'Asset account', 'Cash account']); + + + /** @var Budget $budget */ + foreach ($budgets as $budget) { + // we already have amount, startdate and enddate. + // if this "is" a limit repetition (as opposed to a budget without one entirely) + // depends on whether startdate and enddate are null. + $name = $budget->name; + if (is_null($budget->startdate) && is_null($budget->enddate)) { + $currentStart = clone $start; + $currentEnd = clone $end; + $expenses = $repository->balanceInPeriod($budget, $currentStart, $currentEnd, $accounts); + $amount = '0'; + $left = '0'; + $spent = $expenses; + $overspent = '0'; + } else { + $currentStart = clone $budget->startdate; + $currentEnd = clone $budget->enddate; + $expenses = $repository->balanceInPeriod($budget, $currentStart, $currentEnd, $accounts); + $amount = $budget->amount; + // smaller than 1 means spent MORE than budget allows. + $left = bccomp(bcadd($budget->amount, $expenses), '0') < 1 ? '0' : bcadd($budget->amount, $expenses); + $spent = bccomp(bcadd($budget->amount, $expenses), '0') < 1 ? bcmul($amount, '-1') : $expenses; + $overspent = bccomp(bcadd($budget->amount, $expenses), '0') < 1 ? bcadd($budget->amount, $expenses) : '0'; + } + + $allEntries->push([$name, $left, $spent, $overspent, $amount, $expenses]); + } + + $noBudgetExpenses = $repository->getWithoutBudgetSum($accounts, $start, $end); + $allEntries->push([trans('firefly.noBudget'), '0', '0', $noBudgetExpenses, '0', '0']); + $data = $this->generator->frontpage($allEntries); + $cache->store($data); + + return Response::json($data); + } + /** * * @param BudgetRepositoryInterface $repository @@ -49,7 +218,7 @@ class BudgetController extends Controller * * @return \Illuminate\Http\JsonResponse */ - public function multiYear(BudgetRepositoryInterface $repository, $reportType, Carbon $start, Carbon $end, Collection $accounts, Collection $budgets) + public function multiYear(BudgetRepositoryInterface $repository, string $reportType, Carbon $start, Carbon $end, Collection $accounts, Collection $budgets) { // chart properties for cache: $cache = new CacheProperties(); @@ -87,21 +256,24 @@ class BudgetController extends Controller $currentEnd = clone $currentStart; $currentEnd->endOfYear(); - // save to array: + // basic information: $year = $currentStart->year; - $entry['name'] = $budget->name; + $entry['name'] = $budget->name ?? (string)trans('firefly.noBudget'); $spent = 0; - $budgeted = 0; - if (isset($set[$id]['entries'][$year])) { - $spent = $set[$id]['entries'][$year] * -1; - } - - if (isset($budgetedArray[$id][$year])) { - $budgeted = round($budgetedArray[$id][$year], 2); + // this might be a good moment to collect no budget stuff. + if (is_null($budget->id)) { + // get without budget sum in range: + $spent = $repository->getWithoutBudgetSum($accounts, $currentStart, $currentEnd) * -1; + } else { + if (isset($set[$id]['entries'][$year])) { + $spent = $set[$id]['entries'][$year] * -1; + } } + $budgeted = $budgetedArray[$id][$year] ?? '0'; $entry['spent'][$year] = $spent; - $entry['budgeted'][$year] = $budgeted; + $entry['budgeted'][$year] = round($budgeted, 2); + // jump to next year. $currentStart = clone $currentEnd; @@ -117,181 +289,6 @@ class BudgetController extends Controller } - /** - * @param BudgetRepositoryInterface $repository - * @param Budget $budget - * - * @return \Symfony\Component\HttpFoundation\Response - */ - public function budget(BudgetRepositoryInterface $repository, Budget $budget) - { - - // dates and times - $first = $repository->getFirstBudgetLimitDate($budget); - $range = Preferences::get('viewRange', '1M')->data; - $last = Session::get('end', new Carbon); - - // chart properties for cache: - $cache = new CacheProperties(); - $cache->addProperty($first); - $cache->addProperty($last); - $cache->addProperty('budget'); - if ($cache->has()) { - - return Response::json($cache->get()); // @codeCoverageIgnore - } - - $final = clone $last; - $final->addYears(2); - $last = Navigation::endOfX($last, $range, $final); - $entries = new Collection; - // get all expenses: - $set = $repository->getExpensesPerMonth($budget, $first, $last); - - while ($first < $last) { - $monthFormatted = $first->format('Y-m'); - - $filtered = $set->filter( - function (Budget $obj) use ($monthFormatted) { - return $obj->dateFormatted == $monthFormatted; - } - ); - $spent = is_null($filtered->first()) ? '0' : $filtered->first()->monthlyAmount; - - $entries->push([$first, round(($spent * -1), 2)]); - - $first = Navigation::addPeriod($first, $range, 0); - } - - $data = $this->generator->budget($entries); - $cache->store($data); - - return Response::json($data); - } - - /** - * Shows the amount left in a specific budget limit. - * - * @param BudgetRepositoryInterface $repository - * @param Budget $budget - * @param LimitRepetition $repetition - * - * @return \Symfony\Component\HttpFoundation\Response - */ - public function budgetLimit(BudgetRepositoryInterface $repository, Budget $budget, LimitRepetition $repetition) - { - $start = clone $repetition->startdate; - $end = $repetition->enddate; - bcscale(2); - - // chart properties for cache: - $cache = new CacheProperties(); - $cache->addProperty($start); - $cache->addProperty($end); - $cache->addProperty('budget'); - $cache->addProperty('limit'); - $cache->addProperty($budget->id); - $cache->addProperty($repetition->id); - if ($cache->has()) { - return Response::json($cache->get()); // @codeCoverageIgnore - } - - $set = $repository->getExpensesPerDay($budget, $start, $end); - $entries = new Collection; - $amount = $repetition->amount; - - // get sum (har har)! - while ($start <= $end) { - $formatted = $start->format('Y-m-d'); - $filtered = $set->filter( - function (Budget $obj) use ($formatted) { - return $obj->date == $formatted; - } - ); - $sum = is_null($filtered->first()) ? '0' : $filtered->first()->dailyAmount; - - /* - * Sum of expenses on this day: - */ - $amount = round(bcadd($amount, $sum), 2); - $entries->push([clone $start, $amount]); - $start->addDay(); - } - - $data = $this->generator->budgetLimit($entries); - $cache->store($data); - - return Response::json($data); - - } - - /** - * Shows a budget list with spent/left/overspent. - * - * @param BudgetRepositoryInterface $repository - * - * @param ARI $accountRepository - * - * @return \Symfony\Component\HttpFoundation\Response - */ - public function frontpage(BudgetRepositoryInterface $repository, ARI $accountRepository) - { - $start = Session::get('start', Carbon::now()->startOfMonth()); - $end = Session::get('end', Carbon::now()->endOfMonth()); - - // chart properties for cache: - $cache = new CacheProperties(); - $cache->addProperty($start); - $cache->addProperty($end); - $cache->addProperty('budget'); - $cache->addProperty('all'); - if ($cache->has()) { - return Response::json($cache->get()); // @codeCoverageIgnore - } - - $budgets = $repository->getBudgetsAndLimitsInRange($start, $end); - $allEntries = new Collection; - $accounts = $accountRepository->getAccounts(['Default account', 'Asset account', 'Cash account']); - - - bcscale(2); - - /** @var Budget $budget */ - foreach ($budgets as $budget) { - // we already have amount, startdate and enddate. - // if this "is" a limit repetition (as opposed to a budget without one entirely) - // depends on whether startdate and enddate are null. - $name = $budget->name; - if (is_null($budget->startdate) && is_null($budget->enddate)) { - $currentStart = clone $start; - $currentEnd = clone $end; - $expenses = $repository->balanceInPeriod($budget, $currentStart, $currentEnd, $accounts); - $amount = 0; - $left = 0; - $spent = $expenses; - $overspent = 0; - } else { - $currentStart = clone $budget->startdate; - $currentEnd = clone $budget->enddate; - $expenses = $repository->balanceInPeriod($budget, $currentStart, $currentEnd, $accounts); - $amount = $budget->amount; - // smaller than 1 means spent MORE than budget allows. - $left = bccomp(bcadd($budget->amount, $expenses), '0') < 1 ? 0 : bcadd($budget->amount, $expenses); - $spent = bccomp(bcadd($budget->amount, $expenses), '0') < 1 ? ($amount * -1) : $expenses; - $overspent = bccomp(bcadd($budget->amount, $expenses), '0') < 1 ? bcadd($budget->amount, $expenses) : 0; - } - - $allEntries->push([$name, $left, $spent, $overspent, $amount, $expenses]); - } - - $noBudgetExpenses = $repository->getWithoutBudgetSum($start, $end); - $allEntries->push([trans('firefly.noBudget'), 0, 0, $noBudgetExpenses, 0, 0]); - $data = $this->generator->frontpage($allEntries); - $cache->store($data); - - return Response::json($data); - } - /** * * @param BudgetRepositoryInterface $repository @@ -302,7 +299,7 @@ class BudgetController extends Controller * * @return \Illuminate\Http\JsonResponse */ - public function year(BudgetRepositoryInterface $repository, $reportType, Carbon $start, Carbon $end, Collection $accounts) + public function year(BudgetRepositoryInterface $repository, string $reportType, Carbon $start, Carbon $end, Collection $accounts) { // chart properties for cache: $cache = new CacheProperties(); diff --git a/app/Http/Controllers/Chart/CategoryController.php b/app/Http/Controllers/Chart/CategoryController.php index 95c1985206..b0e5eaf873 100644 --- a/app/Http/Controllers/Chart/CategoryController.php +++ b/app/Http/Controllers/Chart/CategoryController.php @@ -1,4 +1,5 @@ startOfMonth()); - $end = Session::get('end', Carbon::now()->endOfMonth()); + $start = clone session('start', Carbon::now()->startOfMonth()); + $end = session('end', Carbon::now()->endOfMonth()); $data = $this->makePeriodChart($repository, $category, $start, $end); return Response::json($data); @@ -115,7 +120,7 @@ class CategoryController extends Controller * * @return \Illuminate\Http\JsonResponse */ - public function earnedInPeriod(CRI $repository, $reportType, Carbon $start, Carbon $end, Collection $accounts) + public function earnedInPeriod(CRI $repository, string $reportType, Carbon $start, Carbon $end, Collection $accounts) { $cache = new CacheProperties; // chart properties for cache: $cache->addProperty($start); @@ -134,32 +139,8 @@ class CategoryController extends Controller return $category->name; } ); - $entries = new Collection; - - while ($start < $end) { // filter the set: - $row = [clone $start]; - $currentSet = $set->filter( // get possibly relevant entries from the big $set - function (Category $category) use ($start) { - return $category->dateFormatted == $start->format('Y-m'); - } - ); - /** @var Category $category */ - foreach ($categories as $category) { // check for each category if its in the current set. - $entry = $currentSet->filter( // if its in there, use the value. - function (Category $cat) use ($category) { - return ($cat->id == $category->id); - } - )->first(); - if (!is_null($entry)) { - $row[] = round($entry->earned, 2); - } else { - $row[] = 0; - } - } - $entries->push($row); - $start->addMonth(); - } - $data = $this->generator->earnedInPeriod($categories, $entries); + $entries = $this->filterCollection($start, $end, $set, $categories); + $data = $this->generator->earnedInPeriod($categories, $entries); $cache->store($data); return $data; @@ -171,13 +152,15 @@ class CategoryController extends Controller * * @param CRI $repository * + * @param ARI $accountRepository + * * @return \Symfony\Component\HttpFoundation\Response */ - public function frontpage(CRI $repository) + public function frontpage(CRI $repository, ARI $accountRepository) { - $start = Session::get('start', Carbon::now()->startOfMonth()); - $end = Session::get('end', Carbon::now()->endOfMonth()); + $start = session('start', Carbon::now()->startOfMonth()); + $end = session('end', Carbon::now()->endOfMonth()); // chart properties for cache: $cache = new CacheProperties; @@ -190,8 +173,9 @@ class CategoryController extends Controller } // get data for categories (and "no category"): - $set = $repository->spentForAccountsPerMonth(new Collection, $start, $end); - $outside = $repository->sumSpentNoCategory(new Collection, $start, $end); + $accounts = $accountRepository->getAccounts(['Default account', 'Asset account', 'Cash account']); + $set = $repository->spentForAccountsPerMonth($accounts, $start, $end); + $outside = $repository->sumSpentNoCategory($accounts, $start, $end); // this is a "fake" entry for the "no category" entry. $entry = new stdClass(); @@ -216,7 +200,7 @@ class CategoryController extends Controller * * @return \Illuminate\Http\JsonResponse */ - public function multiYear($reportType, Carbon $start, Carbon $end, Collection $accounts, Collection $categories) + public function multiYear(string $reportType, Carbon $start, Carbon $end, Collection $accounts, Collection $categories) { /** @var CRI $repository */ $repository = app('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); @@ -340,42 +324,81 @@ class CategoryController extends Controller return Response::json($cache->get()); // @codeCoverageIgnore } + $set = $repository->spentForAccountsPerMonth($accounts, $start, $end); $categories = $set->unique('id')->sortBy( function (Category $category) { return $category->name; } ); - $entries = new Collection; + $entries = $this->filterCollection($start, $end, $set, $categories); + $entries = $this->invertSelection($entries); + $data = $this->generator->spentInPeriod($categories, $entries); + $cache->store($data); + + return $data; + } + + /** + * @param Carbon $start + * @param Carbon $end + * @param Collection $set + * @param Collection $categories + * + * @return Collection + */ + private function filterCollection(Carbon $start, Carbon $end, Collection $set, Collection $categories): Collection + { + $entries = new Collection; while ($start < $end) { // filter the set: $row = [clone $start]; - $currentSet = $set->filter(// get possibly relevant entries from the big $set + $currentSet = $set->filter( // get possibly relevant entries from the big $set function (Category $category) use ($start) { return $category->dateFormatted == $start->format('Y-m'); } ); /** @var Category $category */ - foreach ($categories as $category) {// check for each category if its in the current set. - $entry = $currentSet->filter(// if its in there, use the value. + foreach ($categories as $category) { // check for each category if its in the current set. + $entry = $currentSet->filter( // if its in there, use the value. function (Category $cat) use ($category) { return ($cat->id == $category->id); } )->first(); if (!is_null($entry)) { - $row[] = round(($entry->spent * -1), 2); + $row[] = $entry->earned ? round($entry->earned, 2) : round($entry->spent, 2); } else { $row[] = 0; } } - $entries->push($row); $start->addMonth(); } - $data = $this->generator->spentInPeriod($categories, $entries); - $cache->store($data); - return $data; + return $entries; + } + + /** + * Not the most elegant solution but it works. + * + * @param Collection $entries + * + * @return Collection + */ + private function invertSelection(Collection $entries): Collection + { + $result = new Collection; + foreach ($entries as $entry) { + $new = [$entry[0]]; + $count = count($entry); + for ($i = 1; $i < $count; $i++) { + $new[$i] = ($entry[$i] * -1); + } + $result->push($new); + } + + return $result; + } /** @@ -395,7 +418,7 @@ class CategoryController extends Controller $cache->addProperty($category->id); $cache->addProperty('specific-period'); if ($cache->has()) { - return $cache->get(); // @codeCoverageIgnore + return $cache->get(); // } $entries = new Collection; @@ -406,8 +429,8 @@ class CategoryController extends Controller while ($start <= $end) { $str = $start->format('Y-m-d'); - $spent = isset($spentArray[$str]) ? $spentArray[$str] : 0; - $earned = isset($earnedArray[$str]) ? $earnedArray[$str] : 0; + $spent = $spentArray[$str] ?? '0'; + $earned = $earnedArray[$str] ?? '0'; $date = Navigation::periodShow($start, '1D'); $entries->push([clone $start, $date, $spent, $earned]); $start->addDay(); @@ -419,5 +442,4 @@ class CategoryController extends Controller return $data; } - } diff --git a/app/Http/Controllers/Chart/PiggyBankController.php b/app/Http/Controllers/Chart/PiggyBankController.php index b21153bfa9..bf2d91a445 100644 --- a/app/Http/Controllers/Chart/PiggyBankController.php +++ b/app/Http/Controllers/Chart/PiggyBankController.php @@ -1,4 +1,5 @@ generator = app('FireflyIII\Generator\Chart\Report\ReportChartGeneratorInterface'); } + /** + * This chart, by default, is shown on the multi-year and year report pages, + * which means that giving it a 2 week "period" should be enough granularity. + * + * @param string $reportType + * @param Carbon $start + * @param Carbon $end + * @param Collection $accounts + * + * @return \Illuminate\Http\JsonResponse + */ + public function netWorth(string $reportType, Carbon $start, Carbon $end, Collection $accounts) + { + // chart properties for cache: + $cache = new CacheProperties; + $cache->addProperty('netWorth'); + $cache->addProperty($start); + $cache->addProperty($reportType); + $cache->addProperty($accounts); + $cache->addProperty($end); + if ($cache->has()) { + return Response::json($cache->get()); // @codeCoverageIgnore + } + $ids = $accounts->pluck('id')->toArray(); + $current = clone $start; + $entries = new Collection; + while ($current < $end) { + $balances = Steam::balancesById($ids, $current); + $sum = $this->arraySum($balances); + $entries->push( + [ + 'date' => clone $current, + 'net-worth' => $sum, + ] + ); + + $current->addDays(7); + } + $data = $this->generator->netWorth($entries); + + $cache->store($data); + + return Response::json($data); + } + /** * Summarizes all income and expenses, per month, for a given year. @@ -45,7 +92,7 @@ class ReportController extends Controller * * @return \Illuminate\Http\JsonResponse */ - public function yearInOut(ReportQueryInterface $query, $reportType, Carbon $start, Carbon $end, Collection $accounts) + public function yearInOut(ReportQueryInterface $query, string $reportType, Carbon $start, Carbon $end, Collection $accounts) { // chart properties for cache: $cache = new CacheProperties; @@ -88,7 +135,7 @@ class ReportController extends Controller * * @return \Illuminate\Http\JsonResponse */ - public function yearInOutSummarized(ReportQueryInterface $query, $reportType, Carbon $start, Carbon $end, Collection $accounts) + public function yearInOutSummarized(ReportQueryInterface $query, string $reportType, Carbon $start, Carbon $end, Collection $accounts) { // chart properties for cache: @@ -117,64 +164,6 @@ class ReportController extends Controller return Response::json($data); } - /** - * @param array $earned - * @param array $spent - * @param Carbon $start - * @param Carbon $end - * - * @return array - */ - protected function singleYearInOutSummarized(array $earned, array $spent, Carbon $start, Carbon $end) - { - $income = '0'; - $expense = '0'; - $count = 0; - while ($start < $end) { - $date = $start->format('Y-m'); - $currentIncome = isset($earned[$date]) ? $earned[$date] : 0; - $currentExpense = isset($spent[$date]) ? ($spent[$date] * -1) : 0; - $income = bcadd($income, $currentIncome); - $expense = bcadd($expense, $currentExpense); - - $count++; - $start->addMonth(); - } - - $data = $this->generator->yearInOutSummarized($income, $expense, $count); - - return $data; - } - - /** - * @param array $earned - * @param array $spent - * @param Carbon $start - * @param Carbon $end - * - * @return array - */ - protected function multiYearInOutSummarized(array $earned, array $spent, Carbon $start, Carbon $end) - { - $income = '0'; - $expense = '0'; - $count = 0; - while ($start < $end) { - - $currentIncome = $this->pluckFromArray($start->year, $earned); - $currentExpense = $this->pluckFromArray($start->year, $spent) * -1; - $income = bcadd($income, $currentIncome); - $expense = bcadd($expense, $currentExpense); - - $count++; - $start->addYear(); - } - - $data = $this->generator->multiYearInOutSummarized($income, $expense, $count); - - return $data; - } - /** * @param array $earned * @param array $spent @@ -208,22 +197,23 @@ class ReportController extends Controller * * @return array */ - protected function singleYearInOut(array $earned, array $spent, Carbon $start, Carbon $end) + protected function multiYearInOutSummarized(array $earned, array $spent, Carbon $start, Carbon $end) { - // per month? simply use each month. - - $entries = new Collection; + $income = '0'; + $expense = '0'; + $count = 0; while ($start < $end) { - // total income and total expenses: - $date = $start->format('Y-m'); - $incomeSum = isset($earned[$date]) ? $earned[$date] : 0; - $expenseSum = isset($spent[$date]) ? ($spent[$date] * -1) : 0; - $entries->push([clone $start, $incomeSum, $expenseSum]); - $start->addMonth(); + $currentIncome = $this->pluckFromArray($start->year, $earned); + $currentExpense = bcmul($this->pluckFromArray($start->year, $spent), '-1'); + $income = bcadd($income, $currentIncome); + $expense = bcadd($expense, $currentExpense); + + $count++; + $start->addYear(); } - $data = $this->generator->yearInOut($entries); + $data = $this->generator->multiYearInOutSummarized($income, $expense, $count); return $data; } @@ -236,7 +226,6 @@ class ReportController extends Controller */ protected function pluckFromArray($year, array $set) { - bcscale(2); $sum = '0'; foreach ($set as $date => $amount) { if (substr($date, 0, 4) == $year) { @@ -247,4 +236,76 @@ class ReportController extends Controller return $sum; } + + /** + * @param array $earned + * @param array $spent + * @param Carbon $start + * @param Carbon $end + * + * @return array + */ + protected function singleYearInOut(array $earned, array $spent, Carbon $start, Carbon $end) + { + // per month? simply use each month. + + $entries = new Collection; + while ($start < $end) { + // total income and total expenses: + $date = $start->format('Y-m'); + $incomeSum = $earned[$date] ?? 0; + $expenseSum = isset($spent[$date]) ? ($spent[$date] * -1) : 0; + + $entries->push([clone $start, $incomeSum, $expenseSum]); + $start->addMonth(); + } + + $data = $this->generator->yearInOut($entries); + + return $data; + } + + /** + * @param array $earned + * @param array $spent + * @param Carbon $start + * @param Carbon $end + * + * @return array + */ + protected function singleYearInOutSummarized(array $earned, array $spent, Carbon $start, Carbon $end) + { + $income = '0'; + $expense = '0'; + $count = 0; + while ($start < $end) { + $date = $start->format('Y-m'); + $currentIncome = $earned[$date] ?? '0'; + $currentExpense = isset($spent[$date]) ? bcmul($spent[$date], '-1') : '0'; + $income = bcadd($income, $currentIncome); + $expense = bcadd($expense, $currentExpense); + + $count++; + $start->addMonth(); + } + + $data = $this->generator->yearInOutSummarized($income, $expense, $count); + + return $data; + } + + /** + * @param $array + * + * @return string + */ + private function arraySum($array) : string + { + $sum = '0'; + foreach ($array as $entry) { + $sum = bcadd($sum, $entry); + } + + return $sum; + } } diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 08328d8884..b3070f64bf 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -1,4 +1,5 @@ data; $this->monthFormat = (string)trans('config.month'); $this->monthAndDayFormat = (string)trans('config.month_and_day'); + $this->dateTimeFormat = (string)trans('config.date_time'); App::setLocale($lang); Carbon::setLocale(substr($lang, 0, 2)); @@ -60,6 +64,7 @@ class Controller extends BaseController ]; View::share('monthFormat', $this->monthFormat); View::share('monthAndDayFormat', $this->monthAndDayFormat); + View::share('dateTimeFormat', $this->dateTimeFormat); View::share('language', $lang); View::share('localeconv', $localeconv); } @@ -77,7 +82,6 @@ class Controller extends BaseController */ protected function getSumOfRange(Carbon $start, Carbon $end, array $array) { - bcscale(2); $sum = '0'; $currentStart = clone $start; // to not mess with the original one $currentEnd = clone $end; // to not mess with the original one diff --git a/app/Http/Controllers/CsvController.php b/app/Http/Controllers/CsvController.php index 75fa433460..b5a7966f32 100644 --- a/app/Http/Controllers/CsvController.php +++ b/app/Http/Controllers/CsvController.php @@ -1,4 +1,5 @@ Session::get('csv-date-format'), - 'has-headers' => Session::get('csv-has-headers'), + 'date-format' => session('csv-date-format'), + 'has-headers' => session('csv-has-headers'), ]; if (Session::has('csv-map')) { - $data['map'] = Session::get('csv-map'); + $data['map'] = session('csv-map'); } if (Session::has('csv-roles')) { - $data['roles'] = Session::get('csv-roles'); + $data['roles'] = session('csv-roles'); } if (Session::has('csv-mapped')) { - $data['mapped'] = Session::get('csv-mapped'); + $data['mapped'] = session('csv-mapped'); } if (Session::has('csv-specifix')) { - $data['specifix'] = Session::get('csv-specifix'); + $data['specifix'] = session('csv-specifix'); } $result = json_encode($data, JSON_PRETTY_PRINT); $name = sprintf('"%s"', addcslashes('csv-configuration-' . date('Y-m-d') . '.json', '"\\')); - RequestFacade::header('Content-disposition: attachment; filename=' . $name); - RequestFacade::header('Content-Type: application/json'); - RequestFacade::header('Content-Description: File Transfer'); - RequestFacade::header('Connection: Keep-Alive'); - RequestFacade::header('Expires: 0'); - RequestFacade::header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); - RequestFacade::header('Pragma: public'); - RequestFacade::header('Content-Length: ' . strlen($result)); - - return $result; + return response($result, 200) + ->header('Content-disposition', 'attachment; filename=' . $name) + ->header('Content-Type', 'application/json') + ->header('Content-Description', 'File Transfer') + ->header('Connection', 'Keep-Alive') + ->header('Expires', '0') + ->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0') + ->header('Pragma', 'public') + ->header('Content-Length', strlen($result)); } /** @@ -218,8 +217,10 @@ class CsvController extends Controller } // process given roles and mapping: - $roles = $this->wizard->processSelectedRoles(Input::get('role')); - $maps = $this->wizard->processSelectedMapping($roles, Input::get('map')); + $inputMap = Input::get('map') ?? []; + $inputRoles = Input::get('role') ?? []; + $roles = $this->wizard->processSelectedRoles($inputRoles); + $maps = $this->wizard->processSelectedMapping($roles, $inputMap); Session::put('csv-map', $maps); Session::put('csv-roles', $roles); @@ -277,13 +278,7 @@ class CsvController extends Controller * field id => field identifier. * ] */ - try { - $options = $this->wizard->showOptions($this->data->getMap()); - } catch (FireflyException $e) { - Log::error($e->getMessage()); - - return view('error', ['message' => $e->getMessage()]); - } + $options = $this->wizard->showOptions($this->data->getMap()); // After these values are prepped, read the actual CSV file $reader = $this->data->getReader(); @@ -318,15 +313,10 @@ class CsvController extends Controller } Log::debug('Created importer'); - $importer = new Importer; + /** @var Importer $importer */ + $importer = app('FireflyIII\Helpers\Csv\Importer'); $importer->setData($this->data); - try { - $importer->run(); - } catch (FireflyException $e) { - Log::error('Catch error: ' . $e->getMessage()); - - return view('error', ['message' => $e->getMessage()]); - } + $importer->run(); Log::debug('Done importing!'); $rows = $importer->getRows(); @@ -408,7 +398,7 @@ class CsvController extends Controller return redirect(route('csv.index')); } - $fullPath = $this->wizard->storeCsvFile($request->file('csv')->getRealPath()); + $path = $this->wizard->storeCsvFile($request->file('csv')->getRealPath()); $settings = []; $settings['date-format'] = Input::get('date_format'); $settings['has-headers'] = intval(Input::get('has_headers')) === 1; @@ -427,14 +417,16 @@ class CsvController extends Controller $settings['roles'] = []; if ($request->hasFile('csv_config')) { // Process config file if present. - $data = file_get_contents($request->file('csv_config')->getRealPath()); + + $size = $request->file('csv_config')->getSize(); + $data = $request->file('csv_config')->openFile()->fread($size); $json = json_decode($data, true); if (is_array($json)) { $settings = array_merge($settings, $json); } } - $this->data->setCsvFileLocation($fullPath); + $this->data->setCsvFileLocation($path); $this->data->setDateFormat($settings['date-format']); $this->data->setHasHeaders($settings['has-headers']); $this->data->setMap($settings['map']); diff --git a/app/Http/Controllers/CurrencyController.php b/app/Http/Controllers/CurrencyController.php index d62ba35cb1..80280c94ca 100644 --- a/app/Http/Controllers/CurrencyController.php +++ b/app/Http/Controllers/CurrencyController.php @@ -22,7 +22,7 @@ class CurrencyController extends Controller /** - * @codeCoverageIgnore + * */ public function __construct() { @@ -40,7 +40,7 @@ class CurrencyController extends Controller $subTitle = trans('firefly.create_currency'); // put previous url in session if not redirect from store (not "create another"). - if (Session::get('currency.create.fromStore') !== true) { + if (session('currency.create.fromStore') !== true) { Session::put('currency.create.url', URL::previous()); } Session::forget('currency.create.fromStore'); @@ -114,7 +114,7 @@ class CurrencyController extends Controller $currency->delete(); } - return redirect(Session::get('currency.delete.url')); + return redirect(session('currency.delete.url')); } /** @@ -129,7 +129,7 @@ class CurrencyController extends Controller $currency->symbol = htmlentities($currency->symbol); // put previous url in session if not redirect from store (not "return_to_edit"). - if (Session::get('currency.edit.fromUpdate') !== true) { + if (session('currency.edit.fromUpdate') !== true) { Session::put('currency.edit.url', URL::previous()); } Session::forget('currency.edit.fromUpdate'); @@ -183,7 +183,7 @@ class CurrencyController extends Controller } // redirect to previous URL. - return redirect(Session::get('currency.create.url')); + return redirect(session('currency.create.url')); } @@ -212,7 +212,7 @@ class CurrencyController extends Controller } // redirect to previous URL. - return redirect(Session::get('currency.edit.url')); + return redirect(session('currency.edit.url')); } diff --git a/app/Http/Controllers/ExportController.php b/app/Http/Controllers/ExportController.php new file mode 100644 index 0000000000..feb72426b6 --- /dev/null +++ b/app/Http/Controllers/ExportController.php @@ -0,0 +1,201 @@ +key . '.zip'; + $date = date('Y-m-d \a\t H-i-s'); + $name = 'Export job on ' . $date . '.zip'; + $quoted = sprintf('"%s"', addcslashes($name, '"\\')); + + if (!$disk->exists($file)) { + throw new FireflyException('Against all expectations, zip file "' . $file . '" does not exist.'); + } + + + $job->change('export_downloaded'); + Log::debug('Will send user file "' . $file . '".'); + + return response($disk->get($file), 200) + ->header('Content-Description', 'File Transfer') + ->header('Content-Type', 'application/octet-stream') + ->header('Content-Disposition', 'attachment; filename=' . $quoted) + ->header('Content-Transfer-Encoding', 'binary') + ->header('Connection', 'Keep-Alive') + ->header('Expires', '0') + ->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0') + ->header('Pragma', 'public') + ->header('Content-Length', $disk->size($file)); + + } + + /** + * @param ExportJob $job + * + * @return \Illuminate\Http\JsonResponse + */ + public function getStatus(ExportJob $job) + { + return Response::json(['status' => trans('firefly.' . $job->status)]); + } + + /** + * @param ARI $repository + * + * @param EJRI $jobs + * + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + */ + public function index(ARI $repository, EJRI $jobs) + { + // create new export job. + $job = $jobs->create(); + // delete old ones. + $jobs->cleanup(); + + // does the user have shared accounts? + $accounts = $repository->getAccounts(['Default account', 'Asset account']); + $accountList = ExpandedForm::makeSelectList($accounts); + $checked = array_keys($accountList); + $formats = array_keys(Config::get('firefly.export_formats')); + $defaultFormat = Preferences::get('export_format', Config::get('firefly.default_export_format'))->data; + $first = session('first')->format('Y-m-d'); + $today = Carbon::create()->format('Y-m-d'); + + return view('export.index', compact('job', 'checked', 'accountList', 'formats', 'defaultFormat', 'first', 'today')); + + } + + /** + * @param ExportFormRequest $request + * @param ARI $repository + * + * @param EJRI $jobs + * + * @return string + * @throws \FireflyIII\Exceptions\FireflyException + */ + public function postIndex(ExportFormRequest $request, ARI $repository, EJRI $jobs) + { + set_time_limit(0); + $job = $jobs->findByKey($request->get('job')); + $settings = [ + 'accounts' => $repository->get($request->get('accounts')), + 'startDate' => new Carbon($request->get('export_start_range')), + 'endDate' => new Carbon($request->get('export_end_range')), + 'exportFormat' => $request->get('exportFormat'), + 'includeAttachments' => intval($request->get('include_attachments')) === 1, + 'includeConfig' => intval($request->get('include_config')) === 1, + 'includeOldUploads' => intval($request->get('include_old_uploads')) === 1, + 'job' => $job, + ]; + + $job->change('export_status_make_exporter'); + $processor = new Processor($settings); + + /* + * Collect journals: + */ + $job->change('export_status_collecting_journals'); + $processor->collectJournals(); + $job->change('export_status_collected_journals'); + /* + * Transform to exportable entries: + */ + $job->change('export_status_converting_to_export_format'); + $processor->convertJournals(); + $job->change('export_status_converted_to_export_format'); + /* + * Transform to (temporary) file: + */ + $job->change('export_status_creating_journal_file'); + $processor->exportJournals(); + $job->change('export_status_created_journal_file'); + /* + * Collect attachments, if applicable. + */ + if ($settings['includeAttachments']) { + $job->change('export_status_collecting_attachments'); + $processor->collectAttachments(); + $job->change('export_status_collected_attachments'); + } + + /* + * Collect old uploads + */ + if ($settings['includeOldUploads']) { + $job->change('export_status_collecting_old_uploads'); + $processor->collectOldUploads(); + $job->change('export_status_collected_old_uploads'); + } + + /* + * Generate / collect config file. + */ + if ($settings['includeConfig']) { + $job->change('export_status_creating_config_file'); + $processor->createConfigFile(); + $job->change('export_status_created_config_file'); + } + + /* + * Create ZIP file: + */ + $job->change('export_status_creating_zip_file'); + $processor->createZipFile(); + $job->change('export_status_created_zip_file'); + + $job->change('export_status_finished'); + + return Response::json('ok'); + } +} diff --git a/app/Http/Controllers/HelpController.php b/app/Http/Controllers/HelpController.php index 667aef28f3..67e177a53d 100644 --- a/app/Http/Controllers/HelpController.php +++ b/app/Http/Controllers/HelpController.php @@ -2,6 +2,7 @@ use FireflyIII\Helpers\Help\HelpInterface; use Log; +use Preferences; use Response; /** @@ -25,7 +26,7 @@ class HelpController extends Controller * * @return \Illuminate\Http\JsonResponse */ - public function show(HelpInterface $help, $route) + public function show(HelpInterface $help, string $route) { $content = [ 'text' => 'There is no help for this route!
', @@ -46,7 +47,8 @@ class HelpController extends Controller return Response::json($content); } - $content = $help->getFromGithub($route); + $language = Preferences::get('language', env('DEFAULT_LANGUAGE', 'en_US'))->data; + $content = $help->getFromGithub($language, $route); $help->putInCache($route, $content); diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 1d638813da..47b2f482d6 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -3,14 +3,17 @@ use Artisan; use Carbon\Carbon; use Config; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Tag; use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI; +use FireflyIII\Repositories\Tag\TagRepositoryInterface; use Input; -use Log; use Preferences; +use Route; use Session; use Steam; + /** * Class HomeController * @@ -28,6 +31,7 @@ class HomeController extends Controller public function dateRange() { + $start = new Carbon(Input::get('start')); $end = new Carbon(Input::get('end')); @@ -42,16 +46,26 @@ class HomeController extends Controller } /** - * @return \Illuminate\Http\RedirectResponse + * @throws FireflyException */ - public function flush() + public function displayError() + { + throw new FireflyException('A very simple test error.'); + } + + /** + * @param TagRepositoryInterface $repository + * + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + */ + public function flush(TagRepositoryInterface $repository) { Preferences::mark(); // get all tags. // update all counts: - $tags = Tag::get(); + $tags = $repository->get(); /** @var Tag $tag */ foreach ($tags as $tag) { @@ -76,22 +90,22 @@ class HomeController extends Controller */ public function index(ARI $repository) { - Log::debug('You are at index.'); $types = Config::get('firefly.accountTypesByIdentifier.asset'); $count = $repository->countAccounts($types); - bcscale(2); if ($count == 0) { return redirect(route('new-user.index')); } - $title = 'Firefly'; - $subTitle = trans('firefly.welcomeBack'); - $mainTitleIcon = 'fa-fire'; - $transactions = []; - $frontPage = Preferences::get('frontPageAccounts', []); - $start = Session::get('start', Carbon::now()->startOfMonth()); - $end = Session::get('end', Carbon::now()->endOfMonth()); + $title = 'Firefly'; + $subTitle = trans('firefly.welcomeBack'); + $mainTitleIcon = 'fa-fire'; + $transactions = []; + $frontPage = Preferences::get('frontPageAccounts', []); + /** @var Carbon $start */ + $start = session('start', Carbon::now()->startOfMonth()); + /** @var Carbon $end */ + $end = session('end', Carbon::now()->endOfMonth()); $showTour = Preferences::get('tour', true)->data; $accounts = $repository->getFrontpageAccounts($frontPage); $savings = $repository->getSavingsAccounts(); @@ -105,11 +119,11 @@ class HomeController extends Controller $sum = $repository->sumOfEverything(); - if ($sum != 0) { + if (bccomp($sum, '0') !== 0) { Session::flash( 'error', 'Your transactions are unbalanced. This means a' . ' withdrawal, deposit or transfer was not stored properly. ' - . 'Please check your accounts and transactions for errors.' + . 'Please check your accounts and transactions for errors (' . $sum . ').' ); } @@ -126,4 +140,52 @@ class HomeController extends Controller ); } + /** + * Display a list of named routes. Excludes some that cannot be "shown". This method + * is used to generate help files (down the road). + */ + public function routes() + { + // these routes are not relevant for the help pages: + $ignore = [ + 'logout', 'register', 'bills.rescan', 'attachments.download', 'attachments.preview', + 'budgets.income', 'csv.download-config', 'currency.default', 'export.status', 'export.download', + 'json.', 'help.', 'piggy-banks.addMoney', 'piggy-banks.removeMoney', 'rules.rule.up', 'rules.rule.down', + 'rules.rule-group.up', 'rules.rule-group.down', 'debugbar', + ]; + $routes = Route::getRoutes(); + /** @var \Illuminate\Routing\Route $route */ + foreach ($routes as $route) { + + $name = $route->getName(); + $methods = $route->getMethods(); + + if (!is_null($name) && in_array('GET', $methods) && !$this->startsWithAny($ignore, $name)) { + foreach (array_keys(Config::get('firefly.languages')) as $lang) { + echo 'touch ' . $lang . '/' . $name . '.mdstorage/logs
for instructions.',
+ 'two_factor_lost_fix_owner' => 'Otherwise, email the site owner, :site_owner and ask them to reset your two factor authentication.',
+
+ // export data:
+ 'import_and_export' => 'Import and export',
+ 'export_data' => 'Export data',
+ 'export_data_intro' => 'For backup purposes, when migrating to another system or when migrating to another Firefly III installation.',
+ 'export_format' => 'Export format',
+ 'export_format_csv' => 'Comma separated values (CSV file)',
+ 'export_format_mt940' => 'MT940 compatible format',
+ 'export_included_accounts' => 'Export transactions from these accounts',
+ 'include_config_help' => 'For easy re-import into Firefly III',
+ 'include_old_uploads_help' => 'Firefly III does not throw away the original CSV files you have imported in the past. You can include them in your export.',
+ 'do_export' => 'Export',
+ 'export_status_never_started' => 'The export has not started yet',
+ 'export_status_make_exporter' => 'Creating exporter thing...',
+ 'export_status_collecting_journals' => 'Collecting your transactions...',
+ 'export_status_collected_journals' => 'Collected your transactions!',
+ 'export_status_converting_to_export_format' => 'Converting your transactions...',
+ 'export_status_converted_to_export_format' => 'Converted your transactions!',
+ 'export_status_creating_journal_file' => 'Creating the export file...',
+ 'export_status_created_journal_file' => 'Created the export file!',
+ 'export_status_collecting_attachments' => 'Collecting all your attachments...',
+ 'export_status_collected_attachments' => 'Collected all your attachments!',
+ 'export_status_collecting_old_uploads' => 'Collecting all your previous uploads...',
+ 'export_status_collected_old_uploads' => 'Collected all your previous uploads!',
+ 'export_status_creating_config_file' => 'Creating a configuration file...',
+ 'export_status_created_config_file' => 'Created a configuration file!',
+ 'export_status_creating_zip_file' => 'Creating a zip file...',
+ 'export_status_created_zip_file' => 'Created a zip file!',
+ 'export_status_finished' => 'Export has succesfully finished! Yay!',
+ 'export_data_please_wait' => 'Please wait...',
+ 'attachment_explanation' => 'The file called \':attachment_name\' (#:attachment_id) was originally uploaded to :type \':description\' (#:journal_id) dated :date for the amount of :amount.',
// rules
- 'rules' => 'Rules',
- 'rules_explanation' => 'Here you can manage rules. Rules are triggered when a transaction is created or updated. Then, if the transaction has certain properties (called "triggers") Firefly will execute the "actions". Combined, you can make Firefly respond in a certain way to new transactions.',
- 'rule_name' => 'Name of rule',
- 'rule_triggers' => 'Rule triggers when',
- 'rule_actions' => 'Rule will',
- 'new_rule' => 'New rule',
- 'new_rule_group' => 'New rule group',
- 'rule_priority_up' => 'Give rule more priority',
- 'rule_priority_down' => 'Give rule less priority',
- 'make_new_rule_group' => 'Make new rule group',
- 'store_new_rule_group' => 'Store new rule group',
- 'created_new_rule_group' => 'New rule group ":title" stored!',
- 'updated_rule_group' => 'Successfully updated rule group ":title".',
- 'edit_rule_group' => 'Edit rule group ":title"',
- 'delete_rule_group' => 'Delete rule group ":title"',
- 'deleted_rule_group' => 'Deleted rule group ":title"',
- 'update_rule_group' => 'Update rule group',
- 'no_rules_in_group' => 'There are no rules in this group',
- 'move_rule_group_up' => 'Move rule group up',
- 'move_rule_group_down' => 'Move rule group down',
- 'save_rules_by_moving' => 'Save these rule(s) by moving them to another rule group:',
- 'make_new_rule' => 'Make new rule in rule group ":title"',
- 'rule_help_stop_processing' => 'When you check this box, later rules in this group will not be executed.',
- 'rule_help_active' => 'Inactive rules will never fire.',
- 'stored_new_rule' => 'Stored new rule with title ":title"',
- 'deleted_rule' => 'Deleted rule with title ":title"',
- 'store_new_rule' => 'Store new rule',
- 'updated_rule' => 'Updated rule with title ":title"',
- 'default_rule_group_name' => 'Default rules',
- 'default_rule_group_description' => 'All your rules not in a particular group.',
- 'default_rule_name' => 'Your first default rule',
- 'default_rule_description' => 'This rule is an example. You can safely delete it.',
- 'default_rule_trigger_description' => 'The Man Who Sold the World',
- 'default_rule_trigger_from_account' => 'David Bowie',
- 'default_rule_action_prepend' => 'Bought the world from ',
- 'default_rule_action_set_category' => 'Large expenses',
-
- 'trigger' => 'Trigger',
- 'trigger_value' => 'Trigger on value',
- 'stop_processing_other_triggers' => 'Stop processing other triggers',
- 'add_rule_trigger' => 'Add new trigger',
- 'action' => 'Action',
- 'action_value' => 'Action value',
- 'stop_executing_other_actions' => 'Stop executing other actions',
- 'add_rule_action' => 'Add new action',
- 'edit_rule' => 'Edit rule ":title"',
- 'update_rule' => 'Update rule',
+ 'rules' => 'Rules',
+ 'rules_explanation' => 'Here you can manage rules. Rules are triggered when a transaction is created or updated. Then, if the transaction has certain properties (called "triggers") Firefly will execute the "actions". Combined, you can make Firefly respond in a certain way to new transactions.',
+ 'rule_name' => 'Name of rule',
+ 'rule_triggers' => 'Rule triggers when',
+ 'rule_actions' => 'Rule will',
+ 'new_rule' => 'New rule',
+ 'new_rule_group' => 'New rule group',
+ 'rule_priority_up' => 'Give rule more priority',
+ 'rule_priority_down' => 'Give rule less priority',
+ 'make_new_rule_group' => 'Make new rule group',
+ 'store_new_rule_group' => 'Store new rule group',
+ 'created_new_rule_group' => 'New rule group ":title" stored!',
+ 'updated_rule_group' => 'Successfully updated rule group ":title".',
+ 'edit_rule_group' => 'Edit rule group ":title"',
+ 'delete_rule_group' => 'Delete rule group ":title"',
+ 'deleted_rule_group' => 'Deleted rule group ":title"',
+ 'update_rule_group' => 'Update rule group',
+ 'no_rules_in_group' => 'There are no rules in this group',
+ 'move_rule_group_up' => 'Move rule group up',
+ 'move_rule_group_down' => 'Move rule group down',
+ 'save_rules_by_moving' => 'Save these rule(s) by moving them to another rule group:',
+ 'make_new_rule' => 'Make new rule in rule group ":title"',
+ 'rule_help_stop_processing' => 'When you check this box, later rules in this group will not be executed.',
+ 'rule_help_active' => 'Inactive rules will never fire.',
+ 'stored_new_rule' => 'Stored new rule with title ":title"',
+ 'deleted_rule' => 'Deleted rule with title ":title"',
+ 'store_new_rule' => 'Store new rule',
+ 'updated_rule' => 'Updated rule with title ":title"',
+ 'default_rule_group_name' => 'Default rules',
+ 'default_rule_group_description' => 'All your rules not in a particular group.',
+ 'default_rule_name' => 'Your first default rule',
+ 'default_rule_description' => 'This rule is an example. You can safely delete it.',
+ 'default_rule_trigger_description' => 'The Man Who Sold the World',
+ 'default_rule_trigger_from_account' => 'David Bowie',
+ 'default_rule_action_prepend' => 'Bought the world from ',
+ 'default_rule_action_set_category' => 'Large expenses',
+ 'trigger' => 'Trigger',
+ 'trigger_value' => 'Trigger on value',
+ 'stop_processing_other_triggers' => 'Stop processing other triggers',
+ 'add_rule_trigger' => 'Add new trigger',
+ 'action' => 'Action',
+ 'action_value' => 'Action value',
+ 'stop_executing_other_actions' => 'Stop executing other actions',
+ 'add_rule_action' => 'Add new action',
+ 'edit_rule' => 'Edit rule ":title"',
+ 'delete_rule' => 'Delete rule ":title"',
+ 'update_rule' => 'Update rule',
+ 'test_rule_triggers' => 'See matching transactions',
+ 'warning_transaction_subset' => 'For performance reasons this list is limited to :max_num_transactions and may only show a subset of matching transactions',
+ 'warning_no_matching_transactions' => 'No matching transactions found. Please note that for performance reasons, only the last :num_transactions transactions have been checked.',
+ 'warning_no_valid_triggers' => 'No valid triggers provided.',
+ 'execute_on_existing_transactions' => 'Execute for existing transactions',
+ 'execute_on_existing_transactions_intro' => 'When a rule or group has been changed or added, you can execute it for existing transactions',
+ 'execute_on_existing_transactions_short' => 'Existing transactions',
+ 'executed_group_on_existing_transactions' => 'Executed group ":title" for existing transactions',
+ 'execute_group_on_existing_transactions' => 'Execute group ":title" for existing transactions',
+ 'include_transactions_from_accounts' => 'Include transactions from these accounts',
+ 'execute' => 'Execute',
// actions and triggers
- 'rule_trigger_user_action' => 'User action is ":trigger_value"',
- 'rule_trigger_from_account_starts' => 'Source account starts with ":trigger_value"',
- 'rule_trigger_from_account_ends' => 'Source account ends with ":trigger_value"',
- 'rule_trigger_from_account_is' => 'Source account is ":trigger_value"',
- 'rule_trigger_from_account_contains' => 'Source account contains ":trigger_value"',
- 'rule_trigger_to_account_starts' => 'Destination account starts with ":trigger_value"',
- 'rule_trigger_to_account_ends' => 'Destination account ends with ":trigger_value"',
- 'rule_trigger_to_account_is' => 'Destination account is ":trigger_value"',
- 'rule_trigger_to_account_contains' => 'Destination account contains ":trigger_value"',
- 'rule_trigger_transaction_type' => 'Transaction is of type ":trigger_value"',
- 'rule_trigger_amount_less' => 'Amount is less than :trigger_value',
- 'rule_trigger_amount_exactly' => 'Amount is :trigger_value',
- 'rule_trigger_amount_more' => 'Amount is more than :trigger_value',
- 'rule_trigger_description_starts' => 'Description starts with ":trigger_value"',
- 'rule_trigger_description_ends' => 'Description ends with ":trigger_value"',
- 'rule_trigger_description_contains' => 'Description contains ":trigger_value"',
- 'rule_trigger_description_is' => 'Description is ":trigger_value"',
-
+ 'rule_trigger_user_action' => 'User action is ":trigger_value"',
+ 'rule_trigger_from_account_starts' => 'Source account starts with ":trigger_value"',
+ 'rule_trigger_from_account_ends' => 'Source account ends with ":trigger_value"',
+ 'rule_trigger_from_account_is' => 'Source account is ":trigger_value"',
+ 'rule_trigger_from_account_contains' => 'Source account contains ":trigger_value"',
+ 'rule_trigger_to_account_starts' => 'Destination account starts with ":trigger_value"',
+ 'rule_trigger_to_account_ends' => 'Destination account ends with ":trigger_value"',
+ 'rule_trigger_to_account_is' => 'Destination account is ":trigger_value"',
+ 'rule_trigger_to_account_contains' => 'Destination account contains ":trigger_value"',
+ 'rule_trigger_transaction_type' => 'Transaction is of type ":trigger_value"',
+ 'rule_trigger_amount_less' => 'Amount is less than :trigger_value',
+ 'rule_trigger_amount_exactly' => 'Amount is :trigger_value',
+ 'rule_trigger_amount_more' => 'Amount is more than :trigger_value',
+ 'rule_trigger_description_starts' => 'Description starts with ":trigger_value"',
+ 'rule_trigger_description_ends' => 'Description ends with ":trigger_value"',
+ 'rule_trigger_description_contains' => 'Description contains ":trigger_value"',
+ 'rule_trigger_description_is' => 'Description is ":trigger_value"',
'rule_trigger_from_account_starts_choice' => 'Source account starts with..',
'rule_trigger_from_account_ends_choice' => 'Source account ends with..',
'rule_trigger_from_account_is_choice' => 'Source account is..',
@@ -122,486 +188,498 @@ return [
'rule_trigger_description_ends_choice' => 'Description ends with..',
'rule_trigger_description_contains_choice' => 'Description contains..',
'rule_trigger_description_is_choice' => 'Description is..',
-
- 'rule_trigger_store_journal' => 'When a journal is created',
- 'rule_trigger_update_journal' => 'When a journal is updated',
-
- 'rule_action_set_category' => 'Set category to ":action_value"',
- 'rule_action_clear_category' => 'Clear category',
- 'rule_action_set_budget' => 'Set budget to ":action_value"',
- 'rule_action_clear_budget' => 'Clear budget',
- 'rule_action_add_tag' => 'Add tag ":action_value"',
- 'rule_action_remove_tag' => 'Remove tag ":action_value"',
- 'rule_action_remove_all_tags' => 'Remove all tags',
- 'rule_action_set_description' => 'Set description to ":action_value"',
- 'rule_action_append_description' => 'Append description with ":action_value"',
- 'rule_action_prepend_description' => 'Prepend description with ":action_value"',
-
- 'rule_action_set_category_choice' => 'Set category to..',
- 'rule_action_clear_category_choice' => 'Clear any category',
- 'rule_action_set_budget_choice' => 'Set budget to..',
- 'rule_action_clear_budget_choice' => 'Clear any budget',
- 'rule_action_add_tag_choice' => 'Add tag..',
- 'rule_action_remove_tag_choice' => 'Remove tag..',
- 'rule_action_remove_all_tags_choice' => 'Remove all tags',
- 'rule_action_set_description_choice' => 'Set description to..',
- 'rule_action_append_description_choice' => 'Append description with..',
- 'rule_action_prepend_description_choice' => 'Prepend description with..',
+ 'rule_trigger_store_journal' => 'When a journal is created',
+ 'rule_trigger_update_journal' => 'When a journal is updated',
+ 'rule_action_set_category' => 'Set category to ":action_value"',
+ 'rule_action_clear_category' => 'Clear category',
+ 'rule_action_set_budget' => 'Set budget to ":action_value"',
+ 'rule_action_clear_budget' => 'Clear budget',
+ 'rule_action_add_tag' => 'Add tag ":action_value"',
+ 'rule_action_remove_tag' => 'Remove tag ":action_value"',
+ 'rule_action_remove_all_tags' => 'Remove all tags',
+ 'rule_action_set_description' => 'Set description to ":action_value"',
+ 'rule_action_append_description' => 'Append description with ":action_value"',
+ 'rule_action_prepend_description' => 'Prepend description with ":action_value"',
+ 'rule_action_set_category_choice' => 'Set category to..',
+ 'rule_action_clear_category_choice' => 'Clear any category',
+ 'rule_action_set_budget_choice' => 'Set budget to..',
+ 'rule_action_clear_budget_choice' => 'Clear any budget',
+ 'rule_action_add_tag_choice' => 'Add tag..',
+ 'rule_action_remove_tag_choice' => 'Remove tag..',
+ 'rule_action_remove_all_tags_choice' => 'Remove all tags',
+ 'rule_action_set_description_choice' => 'Set description to..',
+ 'rule_action_append_description_choice' => 'Append description with..',
+ 'rule_action_prepend_description_choice' => 'Prepend description with..',
// tags
- 'store_new_tag' => 'Store new tag',
- 'update_tag' => 'Update tag',
- 'no_location_set' => 'No location set.',
- 'meta_data' => 'Meta data',
- 'location' => 'Location',
+ 'store_new_tag' => 'Store new tag',
+ 'update_tag' => 'Update tag',
+ 'no_location_set' => 'No location set.',
+ 'meta_data' => 'Meta data',
+ 'location' => 'Location',
// preferences
- 'pref_home_screen_accounts' => 'Home screen accounts',
- 'pref_home_screen_accounts_help' => 'Which accounts should be displayed on the home page?',
- 'pref_budget_settings' => 'Budget settings',
- 'pref_budget_settings_help' => 'What\'s the maximum amount of money a budget envelope may contain?',
- 'pref_view_range' => 'View range',
- 'pref_view_range_help' => 'Some charts are automatically grouped in periods. What period would you prefer?',
- 'pref_1D' => 'One day',
- 'pref_1W' => 'One week',
- 'pref_1M' => 'One month',
- 'pref_3M' => 'Three months (quarter)',
- 'pref_6M' => 'Six months',
- 'pref_languages' => 'Languages',
- 'pref_languages_help' => 'Firefly III supports several languages. Which one do you prefer?',
- 'pref_custom_fiscal_year' => 'Fiscal year settings',
- 'pref_custom_fiscal_year_label' => 'Enabled',
- 'pref_custom_fiscal_year_help' => 'In countries that use a financial year other than January 1 to December 31, you can switch this on and specify start / end days of the fiscal year',
- 'pref_fiscal_year_start_label' => 'Fiscal year start date',
- 'pref_save_settings' => 'Save settings',
+ 'pref_home_screen_accounts' => 'Home screen accounts',
+ 'pref_home_screen_accounts_help' => 'Which accounts should be displayed on the home page?',
+ 'pref_budget_settings' => 'Budget settings',
+ 'pref_budget_settings_help' => 'What\'s the maximum amount of money a budget envelope may contain?',
+ 'pref_view_range' => 'View range',
+ 'pref_view_range_help' => 'Some charts are automatically grouped in periods. What period would you prefer?',
+ 'pref_1D' => 'One day',
+ 'pref_1W' => 'One week',
+ 'pref_1M' => 'One month',
+ 'pref_3M' => 'Three months (quarter)',
+ 'pref_6M' => 'Six months',
+ 'pref_languages' => 'Languages',
+ 'pref_languages_help' => 'Firefly III supports several languages. Which one do you prefer?',
+ 'pref_custom_fiscal_year' => 'Fiscal year settings',
+ 'pref_custom_fiscal_year_label' => 'Enabled',
+ 'pref_custom_fiscal_year_help' => 'In countries that use a financial year other than January 1 to December 31, you can switch this on and specify start / end days of the fiscal year',
+ 'pref_fiscal_year_start_label' => 'Fiscal year start date',
+ 'pref_two_factor_auth' => '2-step verification',
+ 'pref_two_factor_auth_help' => 'When you enable 2-step verification (also known as two-factor authentication), you add an extra layer of security to your account. You sign in with something you know (your password) and something you have (a verification code). Verification codes are generated by an application on your phone, such as Authy or Google Authenticator.',
+ 'pref_enable_two_factor_auth' => 'Enable 2-step verification',
+ 'pref_two_factor_auth_disabled' => '2-step verification code removed and disabled',
+ 'pref_two_factor_auth_remove_it' => 'Don\'t forget to remove the account from your authentication app!',
+ 'pref_two_factor_auth_code' => 'Verify code',
+ 'pref_two_factor_auth_code_help' => 'Scan the QR code with an application on your phone such as Authy or Google Authenticator and enter the generated code.',
+ 'pref_two_factor_auth_reset_code' => 'Reset verification code',
+ 'pref_two_factor_auth_remove_code' => 'Remove verification code',
+ 'pref_two_factor_auth_remove_will_disable' => '(this will also disable two-factor authentication)',
+ 'pref_save_settings' => 'Save settings',
// profile:
- 'change_your_password' => 'Change your password',
- 'delete_account' => 'Delete account',
- 'current_password' => 'Current password',
- 'new_password' => 'New password',
- 'new_password_again' => 'New password (again)',
- 'delete_your_account' => 'Delete your account',
- 'delete_your_account_help' => 'Deleting your account will also delete any accounts, transactions, anything you might have saved into Firefly III. It\'ll be GONE.',
- 'delete_your_account_password' => 'Enter your password to continue.',
- 'password' => 'Password',
- 'are_you_sure' => 'Are you sure? You cannot undo this.',
- 'delete_account_button' => 'DELETE your account',
- 'invalid_current_password' => 'Invalid current password!',
- 'password_changed' => 'Password changed!',
- 'should_change' => 'The idea is to change your password.',
- 'invalid_password' => 'Invalid password!',
+ 'change_your_password' => 'Change your password',
+ 'delete_account' => 'Delete account',
+ 'current_password' => 'Current password',
+ 'new_password' => 'New password',
+ 'new_password_again' => 'New password (again)',
+ 'delete_your_account' => 'Delete your account',
+ 'delete_your_account_help' => 'Deleting your account will also delete any accounts, transactions, anything you might have saved into Firefly III. It\'ll be GONE.',
+ 'delete_your_account_password' => 'Enter your password to continue.',
+ 'password' => 'Password',
+ 'are_you_sure' => 'Are you sure? You cannot undo this.',
+ 'delete_account_button' => 'DELETE your account',
+ 'invalid_current_password' => 'Invalid current password!',
+ 'password_changed' => 'Password changed!',
+ 'should_change' => 'The idea is to change your password.',
+ 'invalid_password' => 'Invalid password!',
// attachments
- 'nr_of_attachments' => 'One attachment|:count attachments',
- 'attachments' => 'Attachments',
- 'edit_attachment' => 'Edit attachment ":name"',
- 'update_attachment' => 'Update attachment',
- 'delete_attachment' => 'Delete attachment ":name"',
- 'attachment_deleted' => 'Deleted attachment ":name"',
- 'upload_max_file_size' => 'Maximum file size: :size',
+ 'nr_of_attachments' => 'One attachment|:count attachments',
+ 'attachments' => 'Attachments',
+ 'edit_attachment' => 'Edit attachment ":name"',
+ 'update_attachment' => 'Update attachment',
+ 'delete_attachment' => 'Delete attachment ":name"',
+ 'attachment_deleted' => 'Deleted attachment ":name"',
+ 'upload_max_file_size' => 'Maximum file size: :size',
// tour:
- 'prev' => 'Prev',
- 'next' => 'Next',
- 'end-tour' => 'End tour',
- 'pause' => 'Pause',
+ 'prev' => 'Prev',
+ 'next' => 'Next',
+ 'end-tour' => 'End tour',
+ 'pause' => 'Pause',
// transaction index
- 'title_expenses' => 'Expenses',
- 'title_withdrawal' => 'Expenses',
- 'title_revenue' => 'Revenue / income',
- 'title_deposit' => 'Revenue / income',
- 'title_transfer' => 'Transfers',
- 'title_transfers' => 'Transfers',
+ 'title_expenses' => 'Expenses',
+ 'title_withdrawal' => 'Expenses',
+ 'title_revenue' => 'Revenue / income',
+ 'title_deposit' => 'Revenue / income',
+ 'title_transfer' => 'Transfers',
+ 'title_transfers' => 'Transfers',
// csv import:
- 'csv_import' => 'Import CSV file',
- 'csv' => 'CSV',
- 'csv_index_title' => 'Upload and import a CSV file',
- 'csv_define_column_roles' => 'Define column roles',
- 'csv_map_values' => 'Map found values to existing values',
- 'csv_download_config' => 'Download CSV configuration file.',
- 'csv_index_text' => 'This form allows you to import a CSV file with transactions into Firefly. It is based on the excellent CSV importer made by the folks at Atlassian. Simply upload your CSV file and follow the instructions. If you would like to learn more, please click on the button at the top of this page.',
- 'csv_index_beta_warning' => 'This tool is very much in beta. Please proceed with caution',
- 'csv_header_help' => 'Check this box when your CSV file\'s first row consists of column names, not actual data',
- 'csv_date_help' => 'Date time format in your CSV. Follow the format like this page indicates. The default value will parse dates that look like this: :dateExample.',
- 'csv_csv_file_help' => 'Select the CSV file here. You can only upload one file at a time',
- 'csv_csv_config_file_help' => 'Select your CSV import configuration here. If you do not know what this is, ignore it. It will be explained later.',
- 'csv_upload_button' => 'Start importing CSV',
- 'csv_column_roles_title' => 'Define column roles',
- 'csv_column_roles_text' => 'Firefly does not know what each column means. You need to indicate what every column is. Please check out the example data if you\'re not sure yourself. Click on the question mark (top right of the page) to learn what each column means. If you want to map imported data onto existing data in Firefly, use the checkbox. The next step will show you what this button does.',
- 'csv_column_roles_table' => 'Column roles',
- 'csv_column' => 'CSV column',
- 'csv_column_name' => 'CSV column name',
- 'csv_column_example' => 'Column example data',
- 'csv_column_role' => 'Column contains?',
- 'csv_do_map_value' => 'Map value?',
- 'csv_continue' => 'Continue to the next step',
- 'csv_go_back' => 'Go back to the previous step',
- 'csv_map_title' => 'Map found values to existing values',
- 'csv_map_text' => 'This page allows you to map the values from the CSV file to existing entries in your database. This ensures that accounts and other things won\'t be created twice.',
- 'csv_field_value' => 'Field value from CSV',
- 'csv_field_mapped_to' => 'Must be mapped to...',
- 'csv_do_not_map' => 'Do not map this value',
- 'csv_download_config_title' => 'Download CSV configuration',
- 'csv_download_config_text' => 'Everything you\'ve just set up can be downloaded as a configuration file. Click the button to do so.',
- 'csv_more_information_text' => 'If the import fails, you can use this configuration file so you don\'t have to start all over again. But, if the import succeeds, it will be easier to upload similar CSV files.',
- 'csv_do_download_config' => 'Download configuration file.',
- 'csv_empty_description' => '(empty description)',
- 'csv_upload_form' => 'CSV upload form',
- 'csv_index_unsupported_warning' => 'The CSV importer is yet incapable of doing the following:',
- 'csv_unsupported_map' => 'The importer cannot map the column ":columnRole" to existing values in the database.',
- 'csv_unsupported_value' => 'The importer does not know how to handle values in columns marked as ":columnRole".',
- 'csv_cannot_store_value' => 'The importer has not reserved space for columns marked ":columnRole" and will be incapable of processing them.',
- 'csv_process_title' => 'CSV import finished!',
- 'csv_process_text' => 'The CSV importer has finished and has processed :rows rows',
- 'csv_row' => 'Row',
- 'csv_import_with_errors' => 'There was one error.|There were :errors errors.',
- 'csv_error_see_logs' => 'Check the log files to see details.',
- 'csv_process_new_entries' => 'Firefly has created :imported new transaction(s).',
- 'csv_start_over' => 'Import again',
- 'csv_to_index' => 'Back home',
- 'csv_upload_not_writeable' => 'Cannot write to the path mentioned here. Cannot upload',
- 'csv_column__ignore' => '(ignore this column)',
- 'csv_column_account-iban' => 'Asset account (IBAN)',
- 'csv_column_account-id' => 'Asset account ID (matching Firefly)',
- 'csv_column_account-name' => 'Asset account (name)',
- 'csv_column_amount' => 'Amount',
- 'csv_column_amount-comma-separated' => 'Amount (comma as decimal separator)',
- 'csv_column_bill-id' => 'Bill ID (matching Firefly)',
- 'csv_column_bill-name' => 'Bill name',
- 'csv_column_budget-id' => 'Budget ID (matching Firefly)',
- 'csv_column_budget-name' => 'Budget name',
- 'csv_column_category-id' => 'Category ID (matching Firefly)',
- 'csv_column_category-name' => 'Category name',
- 'csv_column_currency-code' => 'Currency code (ISO 4217)',
- 'csv_column_currency-id' => 'Currency ID (matching Firefly)',
- 'csv_column_currency-name' => 'Currency name (matching Firefly)',
- 'csv_column_currency-symbol' => 'Currency symbol (matching Firefly)',
- 'csv_column_date-rent' => 'Rent calculation date',
- 'csv_column_date-transaction' => 'Date',
- 'csv_column_description' => 'Description',
- 'csv_column_opposing-iban' => 'Opposing account (IBAN)',
- 'csv_column_opposing-id' => 'Opposing account ID (matching Firefly)',
- 'csv_column_opposing-name' => 'Opposing account (name)',
- 'csv_column_rabo-debet-credit' => 'Rabobank specific debet/credit indicator',
- 'csv_column_sepa-ct-id' => 'SEPA Credit Transfer end-to-end ID',
- 'csv_column_sepa-ct-op' => 'SEPA Credit Transfer opposing account',
- 'csv_column_sepa-db' => 'SEPA Direct Debet',
- 'csv_column_tags-comma' => 'Tags (comma separated)',
- 'csv_column_tags-space' => 'Tags (space separated)',
- 'csv_specifix_RabobankDescription' => 'Select this when you\'re importing Rabobank CSV export files.',
- 'csv_specifix_AbnAmroDescription' => 'Select this when you\'re importing ABN AMRO CSV export files.',
- 'csv_specifix_Dummy' => 'Checking this has no effect whatsoever.',
- 'csv_import_account_help' => 'If your CSV file does NOT contain information about your asset account(s), use this dropdown to select to which account the transactions in the CSV belong to.',
- 'csv_delimiter_help' => 'Choose the field delimiter that is used in your input file. If not sure, comma is the safest option.',
- 'csv_date_parse_error' => 'Could not parse a valid date from ":value", using the format ":format". Are you sure your CSV is correct?',
+ 'csv_import' => 'Import CSV file',
+ 'csv' => 'CSV',
+ 'csv_index_title' => 'Upload and import a CSV file',
+ 'csv_define_column_roles' => 'Define column roles',
+ 'csv_map_values' => 'Map found values to existing values',
+ 'csv_download_config' => 'Download CSV configuration file.',
+ 'csv_index_text' => 'This form allows you to import a CSV file with transactions into Firefly. It is based on the excellent CSV importer made by the folks at Atlassian. Simply upload your CSV file and follow the instructions. If you would like to learn more, please click on the button at the top of this page.',
+ 'csv_index_beta_warning' => 'This tool is very much in beta. Please proceed with caution',
+ 'csv_header_help' => 'Check this box when your CSV file\'s first row consists of column names, not actual data',
+ 'csv_date_help' => 'Date time format in your CSV. Follow the format like this page indicates. The default value will parse dates that look like this: :dateExample.',
+ 'csv_csv_file_help' => 'Select the CSV file here. You can only upload one file at a time',
+ 'csv_csv_config_file_help' => 'Select your CSV import configuration here. If you do not know what this is, ignore it. It will be explained later.',
+ 'csv_upload_button' => 'Start importing CSV',
+ 'csv_column_roles_title' => 'Define column roles',
+ 'csv_column_roles_text' => 'Firefly does not know what each column means. You need to indicate what every column is. Please check out the example data if you\'re not sure yourself. Click on the question mark (top right of the page) to learn what each column means. If you want to map imported data onto existing data in Firefly, use the checkbox. The next step will show you what this button does.',
+ 'csv_column_roles_table' => 'Column roles',
+ 'csv_column' => 'CSV column',
+ 'csv_column_name' => 'CSV column name',
+ 'csv_column_example' => 'Column example data',
+ 'csv_column_role' => 'Column contains?',
+ 'csv_do_map_value' => 'Map value?',
+ 'csv_continue' => 'Continue to the next step',
+ 'csv_go_back' => 'Go back to the previous step',
+ 'csv_map_title' => 'Map found values to existing values',
+ 'csv_map_text' => 'This page allows you to map the values from the CSV file to existing entries in your database. This ensures that accounts and other things won\'t be created twice.',
+ 'csv_field_value' => 'Field value from CSV',
+ 'csv_field_mapped_to' => 'Must be mapped to...',
+ 'csv_do_not_map' => 'Do not map this value',
+ 'csv_download_config_title' => 'Download CSV configuration',
+ 'csv_download_config_text' => 'Everything you\'ve just set up can be downloaded as a configuration file. Click the button to do so.',
+ 'csv_more_information_text' => 'If the import fails, you can use this configuration file so you don\'t have to start all over again. But, if the import succeeds, it will be easier to upload similar CSV files.',
+ 'csv_do_download_config' => 'Download configuration file.',
+ 'csv_empty_description' => '(empty description)',
+ 'csv_upload_form' => 'CSV upload form',
+ 'csv_index_unsupported_warning' => 'The CSV importer is yet incapable of doing the following:',
+ 'csv_unsupported_map' => 'The importer cannot map the column ":columnRole" to existing values in the database.',
+ 'csv_unsupported_value' => 'The importer does not know how to handle values in columns marked as ":columnRole".',
+ 'csv_cannot_store_value' => 'The importer has not reserved space for columns marked ":columnRole" and will be incapable of processing them.',
+ 'csv_process_title' => 'CSV import finished!',
+ 'csv_process_text' => 'The CSV importer has finished and has processed :rows rows',
+ 'csv_row' => 'Row',
+ 'csv_import_with_errors' => 'There was one error.|There were :errors errors.',
+ 'csv_error_see_logs' => 'Check the log files to see details.',
+ 'csv_process_new_entries' => 'Firefly has created :imported new transaction(s).',
+ 'csv_start_over' => 'Import again',
+ 'csv_to_index' => 'Back home',
+ 'csv_upload_not_writeable' => 'Cannot write to the path mentioned here. Cannot upload',
+ 'csv_column__ignore' => '(ignore this column)',
+ 'csv_column_account-iban' => 'Asset account (IBAN)',
+ 'csv_column_account-id' => 'Asset account ID (matching Firefly)',
+ 'csv_column_account-name' => 'Asset account (name)',
+ 'csv_column_amount' => 'Amount',
+ 'csv_column_amount-comma-separated' => 'Amount (comma as decimal separator)',
+ 'csv_column_bill-id' => 'Bill ID (matching Firefly)',
+ 'csv_column_bill-name' => 'Bill name',
+ 'csv_column_budget-id' => 'Budget ID (matching Firefly)',
+ 'csv_column_budget-name' => 'Budget name',
+ 'csv_column_category-id' => 'Category ID (matching Firefly)',
+ 'csv_column_category-name' => 'Category name',
+ 'csv_column_currency-code' => 'Currency code (ISO 4217)',
+ 'csv_column_currency-id' => 'Currency ID (matching Firefly)',
+ 'csv_column_currency-name' => 'Currency name (matching Firefly)',
+ 'csv_column_currency-symbol' => 'Currency symbol (matching Firefly)',
+ 'csv_column_date-rent' => 'Rent calculation date',
+ 'csv_column_date-transaction' => 'Date',
+ 'csv_column_description' => 'Description',
+ 'csv_column_opposing-iban' => 'Opposing account (IBAN)',
+ 'csv_column_opposing-id' => 'Opposing account ID (matching Firefly)',
+ 'csv_column_opposing-name' => 'Opposing account (name)',
+ 'csv_column_rabo-debet-credit' => 'Rabobank specific debet/credit indicator',
+ 'csv_column_ing-debet-credit' => 'ING specific debet/credit indicator',
+ 'csv_column_sepa-ct-id' => 'SEPA Credit Transfer end-to-end ID',
+ 'csv_column_sepa-ct-op' => 'SEPA Credit Transfer opposing account',
+ 'csv_column_sepa-db' => 'SEPA Direct Debet',
+ 'csv_column_tags-comma' => 'Tags (comma separated)',
+ 'csv_column_tags-space' => 'Tags (space separated)',
+ 'csv_column_account-number' => 'Asset account (account number)',
+ 'csv_column_opposing-number' => 'Opposing account (account number)',
+ 'csv_specifix_RabobankDescription' => 'Select this when you\'re importing Rabobank CSV export files.',
+ 'csv_specifix_AbnAmroDescription' => 'Select this when you\'re importing ABN AMRO CSV export files.',
+ 'csv_specifix_Dummy' => 'Checking this has no effect whatsoever.',
+ 'csv_import_account_help' => 'If your CSV file does NOT contain information about your asset account(s), use this dropdown to select to which account the transactions in the CSV belong to.',
+ 'csv_delimiter_help' => 'Choose the field delimiter that is used in your input file. If not sure, comma is the safest option.',
+ 'csv_date_parse_error' => 'Could not parse a valid date from ":value", using the format ":format". Are you sure your CSV is correct?',
// create new stuff:
- 'create_new_withdrawal' => 'Create new withdrawal',
- 'create_new_deposit' => 'Create new deposit',
- 'create_new_transfer' => 'Create new transfer',
- 'create_new_asset' => 'Create new asset account',
- 'create_new_expense' => 'Create new expense account',
- 'create_new_revenue' => 'Create new revenue account',
- 'create_new_piggy_bank' => 'Create new piggy bank',
- 'create_new_bill' => 'Create new bill',
+ 'create_new_withdrawal' => 'Create new withdrawal',
+ 'create_new_deposit' => 'Create new deposit',
+ 'create_new_transfer' => 'Create new transfer',
+ 'create_new_asset' => 'Create new asset account',
+ 'create_new_expense' => 'Create new expense account',
+ 'create_new_revenue' => 'Create new revenue account',
+ 'create_new_piggy_bank' => 'Create new piggy bank',
+ 'create_new_bill' => 'Create new bill',
// currencies:
- 'create_currency' => 'Create a new currency',
- 'edit_currency' => 'Edit currency ":name"',
- 'store_currency' => 'Store new currency',
- 'update_currency' => 'Update currency',
- 'new_default_currency' => ':name is now the default currency.',
- 'cannot_delete_currency' => 'Cannot delete :name because there are still transactions attached to it!',
- 'deleted_currency' => 'Currency :name deleted',
- 'created_currency' => 'Currency :name created',
- 'updated_currency' => 'Currency :name updated',
- 'ask_site_owner' => 'Please ask :owner to add, remove or edit currencies.',
- 'currencies_intro' => 'Firefly III supports various currencies which you can set and enable here.',
- 'make_default_currency' => 'make default',
- 'default_currency' => 'default',
+ 'create_currency' => 'Create a new currency',
+ 'edit_currency' => 'Edit currency ":name"',
+ 'store_currency' => 'Store new currency',
+ 'update_currency' => 'Update currency',
+ 'new_default_currency' => ':name is now the default currency.',
+ 'cannot_delete_currency' => 'Cannot delete :name because there are still transactions attached to it!',
+ 'deleted_currency' => 'Currency :name deleted',
+ 'created_currency' => 'Currency :name created',
+ 'updated_currency' => 'Currency :name updated',
+ 'ask_site_owner' => 'Please ask :owner to add, remove or edit currencies.',
+ 'currencies_intro' => 'Firefly III supports various currencies which you can set and enable here.',
+ 'make_default_currency' => 'make default',
+ 'default_currency' => 'default',
// new user:
- 'submit' => 'Submit',
- 'getting_started' => 'Getting started',
- 'to_get_started' => 'To get started with Firefly, please enter your current bank\'s name, and the balance of your checking account:',
- 'savings_balance_text' => 'If you have a savings account, please enter the current balance of your savings account:',
- 'cc_balance_text' => 'If you have a credit card, please enter your credit card\'s limit.',
+ 'submit' => 'Submit',
+ 'getting_started' => 'Getting started',
+ 'to_get_started' => 'To get started with Firefly, please enter your current bank\'s name, and the balance of your checking account:',
+ 'savings_balance_text' => 'If you have a savings account, please enter the current balance of your savings account:',
+ 'cc_balance_text' => 'If you have a credit card, please enter your credit card\'s limit.',
// forms:
- 'mandatoryFields' => 'Mandatory fields',
- 'optionalFields' => 'Optional fields',
- 'options' => 'Options',
- 'something' => 'Something!',
+ 'mandatoryFields' => 'Mandatory fields',
+ 'optionalFields' => 'Optional fields',
+ 'options' => 'Options',
+ 'something' => 'Something!',
// budgets:
- 'create_new_budget' => 'Create a new budget',
- 'store_new_budget' => ' Store new budget',
- 'availableIn' => 'Available in :date',
- 'transactionsWithoutBudget' => 'Expenses without budget',
- 'transactionsWithoutBudgetDate' => 'Expenses without budget in :date',
- 'createBudget' => 'New budget',
- 'inactiveBudgets' => 'Inactive budgets',
- 'without_budget_between' => 'Transactions without a budget between :start and :end',
- 'budget_in_month' => ':name in :month',
- 'delete_budget' => 'Delete budget ":name"',
- 'edit_budget' => 'Edit budget ":name"',
- 'update_amount' => 'Update amount',
- 'update_budget' => 'Update budget',
+ 'create_new_budget' => 'Create a new budget',
+ 'store_new_budget' => ' Store new budget',
+ 'availableIn' => 'Available in :date',
+ 'transactionsWithoutBudget' => 'Expenses without budget',
+ 'transactionsWithoutBudgetDate' => 'Expenses without budget in :date',
+ 'createBudget' => 'New budget',
+ 'inactiveBudgets' => 'Inactive budgets',
+ 'without_budget_between' => 'Transactions without a budget between :start and :end',
+ 'budget_in_month' => ':name in :month',
+ 'delete_budget' => 'Delete budget ":name"',
+ 'edit_budget' => 'Edit budget ":name"',
+ 'update_amount' => 'Update amount',
+ 'update_budget' => 'Update budget',
// bills:
- 'delete_bill' => 'Delete bill ":name"',
- 'edit_bill' => 'Edit bill ":name"',
- 'update_bill' => 'Update bill',
- 'store_new_bill' => 'Store new bill',
+ 'delete_bill' => 'Delete bill ":name"',
+ 'edit_bill' => 'Edit bill ":name"',
+ 'update_bill' => 'Update bill',
+ 'store_new_bill' => 'Store new bill',
// accounts:
- 'details_for_asset' => 'Details for asset account ":name"',
- 'details_for_expense' => 'Details for expense account ":name"',
- 'details_for_revenue' => 'Details for revenue account ":name"',
- 'details_for_cash' => 'Details for cash account ":name"',
- 'store_new_asset_account' => 'Store new asset account',
- 'store_new_expense_account' => 'Store new expense account',
- 'store_new_revenue_account' => 'Store new revenue account',
- 'edit_asset_account' => 'Edit asset account ":name"',
- 'edit_expense_account' => 'Edit expense account ":name"',
- 'edit_revenue_account' => 'Edit revenue account ":name"',
- 'delete_asset_account' => 'Delete asset account ":name"',
- 'delete_expense_account' => 'Delete expense account ":name"',
- 'delete_revenue_account' => 'Delete revenue account ":name"',
- 'asset_deleted' => 'Successfully deleted asset account ":name"',
- 'expense_deleted' => 'Successfully deleted expense account ":name"',
- 'revenue_deleted' => 'Successfully deleted revenue account ":name"',
- 'update_asset_account' => 'Update asset account',
- 'update_expense_account' => 'Update expense account',
- 'update_revenue_account' => 'Update revenue account',
- 'make_new_asset_account' => 'Create a new asset account',
- 'make_new_expense_account' => 'Create a new expense account',
- 'make_new_revenue_account' => 'Create a new revenue account',
- 'asset_accounts' => 'Asset accounts',
- 'expense_accounts' => 'Expense accounts',
- 'revenue_accounts' => 'Revenue accounts',
- 'accountExtraHelp_asset' => '',
- 'accountExtraHelp_expense' => '',
- 'accountExtraHelp_revenue' => '',
- 'account_type' => 'Account type',
- 'save_transactions_by_moving' => 'Save these transaction(s) by moving them to another account:',
+ 'details_for_asset' => 'Details for asset account ":name"',
+ 'details_for_expense' => 'Details for expense account ":name"',
+ 'details_for_revenue' => 'Details for revenue account ":name"',
+ 'details_for_cash' => 'Details for cash account ":name"',
+ 'store_new_asset_account' => 'Store new asset account',
+ 'store_new_expense_account' => 'Store new expense account',
+ 'store_new_revenue_account' => 'Store new revenue account',
+ 'edit_asset_account' => 'Edit asset account ":name"',
+ 'edit_expense_account' => 'Edit expense account ":name"',
+ 'edit_revenue_account' => 'Edit revenue account ":name"',
+ 'delete_asset_account' => 'Delete asset account ":name"',
+ 'delete_expense_account' => 'Delete expense account ":name"',
+ 'delete_revenue_account' => 'Delete revenue account ":name"',
+ 'asset_deleted' => 'Successfully deleted asset account ":name"',
+ 'expense_deleted' => 'Successfully deleted expense account ":name"',
+ 'revenue_deleted' => 'Successfully deleted revenue account ":name"',
+ 'update_asset_account' => 'Update asset account',
+ 'update_expense_account' => 'Update expense account',
+ 'update_revenue_account' => 'Update revenue account',
+ 'make_new_asset_account' => 'Create a new asset account',
+ 'make_new_expense_account' => 'Create a new expense account',
+ 'make_new_revenue_account' => 'Create a new revenue account',
+ 'asset_accounts' => 'Asset accounts',
+ 'expense_accounts' => 'Expense accounts',
+ 'revenue_accounts' => 'Revenue accounts',
+ 'accountExtraHelp_asset' => '',
+ 'accountExtraHelp_expense' => '',
+ 'accountExtraHelp_revenue' => '',
+ 'account_type' => 'Account type',
+ 'save_transactions_by_moving' => 'Save these transaction(s) by moving them to another account:',
// categories:
- 'new_category' => 'New category',
- 'create_new_category' => 'Create a new category',
- 'without_category' => 'Without a category',
- 'update_category' => 'Wijzig categorie',
- 'categories' => 'Categories',
- 'edit_category' => 'Edit category ":name"',
- 'no_category' => '(no category)',
- 'category' => 'Category',
- 'delete_category' => 'Delete category ":name"',
- 'store_category' => 'Store new category',
- 'without_category_between' => 'Without category between :start and :end',
+ 'new_category' => 'New category',
+ 'create_new_category' => 'Create a new category',
+ 'without_category' => 'Without a category',
+ 'update_category' => 'Wijzig categorie',
+ 'categories' => 'Categories',
+ 'edit_category' => 'Edit category ":name"',
+ 'no_category' => '(no category)',
+ 'category' => 'Category',
+ 'delete_category' => 'Delete category ":name"',
+ 'store_category' => 'Store new category',
+ 'without_category_between' => 'Without category between :start and :end',
// transactions:
- 'update_withdrawal' => 'Update withdrawal',
- 'update_deposit' => 'Update deposit',
- 'update_transfer' => 'Update transfer',
- 'delete_withdrawal' => 'Delete withdrawal ":description"',
- 'delete_deposit' => 'Delete deposit ":description"',
- 'delete_transfer' => 'Delete transfer ":description"',
+ 'update_withdrawal' => 'Update withdrawal',
+ 'update_deposit' => 'Update deposit',
+ 'update_transfer' => 'Update transfer',
+ 'delete_withdrawal' => 'Delete withdrawal ":description"',
+ 'delete_deposit' => 'Delete deposit ":description"',
+ 'delete_transfer' => 'Delete transfer ":description"',
// new user:
- 'welcome' => 'Welcome to Firefly!',
- 'createNewAsset' => 'Create a new asset account to get started. ' .
- 'This will allow you to create transactions and start your financial management',
- 'createNewAssetButton' => 'Create new asset account',
+ 'welcome' => 'Welcome to Firefly!',
+ 'createNewAsset' => 'Create a new asset account to get started. ' .
+ 'This will allow you to create transactions and start your financial management',
+ 'createNewAssetButton' => 'Create new asset account',
// home page:
- 'yourAccounts' => 'Your accounts',
- 'budgetsAndSpending' => 'Budgets and spending',
- 'savings' => 'Savings',
- 'markAsSavingsToContinue' => 'Mark your asset accounts as "Savings account" to fill this panel',
- 'createPiggyToContinue' => 'Create piggy banks to fill this panel.',
- 'newWithdrawal' => 'New expense',
- 'newDeposit' => 'New deposit',
- 'newTransfer' => 'New transfer',
- 'moneyIn' => 'Money in',
- 'moneyOut' => 'Money out',
- 'billsToPay' => 'Bills to pay',
- 'billsPaid' => 'Bills paid',
- 'viewDetails' => 'View details',
- 'divided' => 'divided',
- 'toDivide' => 'left to divide',
+ 'yourAccounts' => 'Your accounts',
+ 'budgetsAndSpending' => 'Budgets and spending',
+ 'savings' => 'Savings',
+ 'markAsSavingsToContinue' => 'Mark your asset accounts as "Savings account" to fill this panel',
+ 'createPiggyToContinue' => 'Create piggy banks to fill this panel.',
+ 'newWithdrawal' => 'New expense',
+ 'newDeposit' => 'New deposit',
+ 'newTransfer' => 'New transfer',
+ 'moneyIn' => 'Money in',
+ 'moneyOut' => 'Money out',
+ 'billsToPay' => 'Bills to pay',
+ 'billsPaid' => 'Bills paid',
+ 'viewDetails' => 'View details',
+ 'divided' => 'divided',
+ 'toDivide' => 'left to divide',
// menu and titles, should be recycled as often as possible:
- 'toggleNavigation' => 'Toggle navigation',
- 'currency' => 'Currency',
- 'preferences' => 'Preferences',
- 'logout' => 'Logout',
- 'searchPlaceholder' => 'Search...',
- 'dashboard' => 'Dashboard',
- 'currencies' => 'Currencies',
- 'accounts' => 'Accounts',
- 'Asset account' => 'Asset account',
- 'Default account' => 'Asset account',
- 'Expense account' => 'Expense account',
- 'Revenue account' => 'Revenue account',
- 'Initial balance account' => 'Initial balance account',
- 'budgets' => 'Budgets',
- 'tags' => 'Tags',
- 'reports' => 'Reports',
- 'transactions' => 'Transactions',
- 'expenses' => 'Expenses',
- 'income' => 'Revenue / income',
- 'transfers' => 'Transfers',
- 'moneyManagement' => 'Money management',
- 'piggyBanks' => 'Piggy banks',
- 'bills' => 'Bills',
- 'createNew' => 'Create new',
- 'withdrawal' => 'Withdrawal',
- 'deposit' => 'Deposit',
- 'account' => 'Account',
- 'transfer' => 'Transfer',
- 'Withdrawal' => 'Withdrawal',
- 'Deposit' => 'Deposit',
- 'Transfer' => 'Transfer',
- 'bill' => 'Bill',
- 'yes' => 'Yes',
- 'no' => 'No',
- 'amount' => 'Amount',
- 'newBalance' => 'New balance',
- 'overview' => 'Overview',
- 'saveOnAccount' => 'Save on account',
- 'unknown' => 'Unknown',
- 'daily' => 'Daily',
- 'weekly' => 'Weekly',
- 'monthly' => 'Monthly',
- 'quarterly' => 'Quarterly',
- 'half-year' => 'Every six months',
- 'yearly' => 'Yearly',
- 'profile' => 'Profile',
+ 'toggleNavigation' => 'Toggle navigation',
+ 'currency' => 'Currency',
+ 'preferences' => 'Preferences',
+ 'logout' => 'Logout',
+ 'searchPlaceholder' => 'Search...',
+ 'dashboard' => 'Dashboard',
+ 'currencies' => 'Currencies',
+ 'accounts' => 'Accounts',
+ 'Asset account' => 'Asset account',
+ 'Default account' => 'Asset account',
+ 'Expense account' => 'Expense account',
+ 'Revenue account' => 'Revenue account',
+ 'Initial balance account' => 'Initial balance account',
+ 'budgets' => 'Budgets',
+ 'tags' => 'Tags',
+ 'reports' => 'Reports',
+ 'transactions' => 'Transactions',
+ 'expenses' => 'Expenses',
+ 'income' => 'Revenue / income',
+ 'transfers' => 'Transfers',
+ 'moneyManagement' => 'Money management',
+ 'piggyBanks' => 'Piggy banks',
+ 'bills' => 'Bills',
+ 'createNew' => 'Create new',
+ 'withdrawal' => 'Withdrawal',
+ 'deposit' => 'Deposit',
+ 'account' => 'Account',
+ 'transfer' => 'Transfer',
+ 'Withdrawal' => 'Withdrawal',
+ 'Deposit' => 'Deposit',
+ 'Transfer' => 'Transfer',
+ 'bill' => 'Bill',
+ 'yes' => 'Yes',
+ 'no' => 'No',
+ 'amount' => 'Amount',
+ 'newBalance' => 'New balance',
+ 'overview' => 'Overview',
+ 'saveOnAccount' => 'Save on account',
+ 'unknown' => 'Unknown',
+ 'daily' => 'Daily',
+ 'weekly' => 'Weekly',
+ 'monthly' => 'Monthly',
+ 'quarterly' => 'Quarterly',
+ 'half-year' => 'Every six months',
+ 'yearly' => 'Yearly',
+ 'profile' => 'Profile',
// reports:
- 'report_default' => 'Default financial report for :start until :end',
- 'quick_link_reports' => 'Quick links',
- 'quick_link_default_report' => 'Default financial report',
- 'report_this_month_quick' => 'Current month, all accounts',
- 'report_this_year_quick' => 'Current year, all accounts',
- 'report_this_fiscal_year_quick' => 'Current fiscal year, all accounts',
- 'report_all_time_quick' => 'All-time, all accounts',
- 'reports_can_bookmark' => 'Remember that reports can be bookmarked.',
- 'incomeVsExpenses' => 'Income vs. expenses',
- 'accountBalances' => 'Account balances',
- 'balanceStartOfYear' => 'Balance at start of year',
- 'balanceEndOfYear' => 'Balance at end of year',
- 'balanceStartOfMonth' => 'Balance at start of month',
- 'balanceEndOfMonth' => 'Balance at end of month',
- 'balanceStart' => 'Balance at start of period',
- 'balanceEnd' => 'Balance at end of period',
- 'reportsOwnAccounts' => 'Reports for your own accounts',
- 'reportsOwnAccountsAndShared' => 'Reports for your own accounts and shared accounts',
- 'splitByAccount' => 'Split by account',
- 'balancedByTransfersAndTags' => 'Balanced by transfers and tags',
- 'coveredWithTags' => 'Covered with tags',
- 'leftUnbalanced' => 'Left unbalanced',
- 'expectedBalance' => 'Expected balance',
- 'outsideOfBudgets' => 'Outside of budgets',
- 'leftInBudget' => 'Left in budget',
- 'sumOfSums' => 'Sum of sums',
- 'noCategory' => '(no category)',
- 'notCharged' => 'Not charged (yet)',
- 'inactive' => 'Inactive',
- 'difference' => 'Difference',
- 'in' => 'In',
- 'out' => 'Out',
- 'topX' => 'top :number',
- 'showTheRest' => 'Show everything',
- 'hideTheRest' => 'Show only the top :number',
- 'sum_of_year' => 'Sum of year',
- 'sum_of_years' => 'Sum of years',
- 'average_of_year' => 'Average of year',
- 'average_of_years' => 'Average of years',
- 'categories_earned_in_year' => 'Categories (by earnings)',
- 'categories_spent_in_year' => 'Categories (by spendings)',
- 'report_type' => 'Report type',
- 'report_type_default' => 'Default financial report',
- 'report_included_accounts' => 'Included accounts',
- 'report_date_range' => 'Date range',
- 'report_include_help' => 'In all cases, transfers to shared accounts count as expenses, and transfers from shared accounts count as income.',
- 'report_preset_ranges' => 'Pre-set ranges',
- 'shared' => 'Shared',
- 'fiscal_year' => 'Fiscal year',
+ 'report_default' => 'Default financial report for :start until :end',
+ 'report_audit' => 'Transaction history overview for :start until :end',
+ 'quick_link_reports' => 'Quick links',
+ 'quick_link_default_report' => 'Default financial report',
+ 'report_this_month_quick' => 'Current month, all accounts',
+ 'report_this_year_quick' => 'Current year, all accounts',
+ 'report_this_fiscal_year_quick' => 'Current fiscal year, all accounts',
+ 'report_all_time_quick' => 'All-time, all accounts',
+ 'reports_can_bookmark' => 'Remember that reports can be bookmarked.',
+ 'incomeVsExpenses' => 'Income vs. expenses',
+ 'accountBalances' => 'Account balances',
+ 'balanceStartOfYear' => 'Balance at start of year',
+ 'balanceEndOfYear' => 'Balance at end of year',
+ 'balanceStartOfMonth' => 'Balance at start of month',
+ 'balanceEndOfMonth' => 'Balance at end of month',
+ 'balanceStart' => 'Balance at start of period',
+ 'balanceEnd' => 'Balance at end of period',
+ 'reportsOwnAccounts' => 'Reports for your own accounts',
+ 'reportsOwnAccountsAndShared' => 'Reports for your own accounts and shared accounts',
+ 'splitByAccount' => 'Split by account',
+ 'balancedByTransfersAndTags' => 'Balanced by transfers and tags',
+ 'coveredWithTags' => 'Covered with tags',
+ 'leftUnbalanced' => 'Left unbalanced',
+ 'expectedBalance' => 'Expected balance',
+ 'outsideOfBudgets' => 'Outside of budgets',
+ 'leftInBudget' => 'Left in budget',
+ 'sumOfSums' => 'Sum of sums',
+ 'noCategory' => '(no category)',
+ 'notCharged' => 'Not charged (yet)',
+ 'inactive' => 'Inactive',
+ 'difference' => 'Difference',
+ 'in' => 'In',
+ 'out' => 'Out',
+ 'topX' => 'top :number',
+ 'showTheRest' => 'Show everything',
+ 'hideTheRest' => 'Show only the top :number',
+ 'sum_of_year' => 'Sum of year',
+ 'sum_of_years' => 'Sum of years',
+ 'average_of_year' => 'Average of year',
+ 'average_of_years' => 'Average of years',
+ 'categories_earned_in_year' => 'Categories (by earnings)',
+ 'categories_spent_in_year' => 'Categories (by spendings)',
+ 'report_type' => 'Report type',
+ 'report_type_default' => 'Default financial report',
+ 'report_type_audit' => 'Transaction history overview (audit)',
+ 'report_included_accounts' => 'Included accounts',
+ 'report_date_range' => 'Date range',
+ 'report_include_help' => 'In all cases, transfers to shared accounts count as expenses, and transfers from shared accounts count as income.',
+ 'report_preset_ranges' => 'Pre-set ranges',
+ 'shared' => 'Shared',
+ 'fiscal_year' => 'Fiscal year',
// charts:
- 'dayOfMonth' => 'Day of the month',
- 'month' => 'Month',
- 'budget' => 'Budget',
- 'spent' => 'Spent',
- 'earned' => 'Earned',
- 'overspent' => 'Overspent',
- 'left' => 'Left',
- 'noBudget' => '(no budget)',
- 'maxAmount' => 'Maximum amount',
- 'minAmount' => 'Minumum amount',
- 'billEntry' => 'Current bill entry',
- 'name' => 'Name',
- 'date' => 'Date',
- 'paid' => 'Paid',
- 'unpaid' => 'Unpaid',
- 'day' => 'Day',
- 'budgeted' => 'Budgeted',
- 'period' => 'Period',
- 'balance' => 'Balance',
- 'summary' => 'Summary',
- 'sum' => 'Sum',
- 'average' => 'Average',
- 'balanceFor' => 'Balance for :name',
+ 'dayOfMonth' => 'Day of the month',
+ 'month' => 'Month',
+ 'budget' => 'Budget',
+ 'spent' => 'Spent',
+ 'earned' => 'Earned',
+ 'overspent' => 'Overspent',
+ 'left' => 'Left',
+ 'noBudget' => '(no budget)',
+ 'maxAmount' => 'Maximum amount',
+ 'minAmount' => 'Minumum amount',
+ 'billEntry' => 'Current bill entry',
+ 'name' => 'Name',
+ 'date' => 'Date',
+ 'paid' => 'Paid',
+ 'unpaid' => 'Unpaid',
+ 'day' => 'Day',
+ 'budgeted' => 'Budgeted',
+ 'period' => 'Period',
+ 'balance' => 'Balance',
+ 'summary' => 'Summary',
+ 'sum' => 'Sum',
+ 'average' => 'Average',
+ 'balanceFor' => 'Balance for :name',
// piggy banks:
- 'piggy_bank' => 'Piggy bank',
- 'new_piggy_bank' => 'Create new piggy bank',
- 'store_piggy_bank' => 'Store new piggy bank',
- 'account_status' => 'Account status',
- 'left_for_piggy_banks' => 'Left for piggy banks',
- 'sum_of_piggy_banks' => 'Sum of piggy banks',
- 'saved_so_far' => 'Saved so far',
- 'left_to_save' => 'Left to save',
- 'add_money_to_piggy_title' => 'Add money to piggy bank ":name"',
- 'remove_money_from_piggy_title' => 'Remove money from piggy bank ":name"',
- 'add' => 'Add',
- 'remove' => 'Remove',
- 'max_amount_add' => 'The maximum amount you can add is',
- 'max_amount_remove' => 'The maximum amount you can remove is',
- 'update_piggy_button' => 'Update piggy bank',
- 'update_piggy_title' => 'Update piggy bank ":name"',
- 'details' => 'Details',
- 'events' => 'Events',
- 'target_amount' => 'Target amount',
- 'start_date' => 'Start date',
- 'target_date' => 'Target date',
- 'no_target_date' => 'No target date',
- 'todo' => 'to do',
- 'table' => 'Table',
- 'piggy_bank_not_exists' => 'Piggy bank no longer exists.',
- 'add_any_amount_to_piggy' => 'Add money to this piggy bank to reach your target of :amount.',
- 'add_set_amount_to_piggy' => 'Add :amount to fill this piggy bank on :date',
- 'delete_piggy_bank' => 'Delete piggy bank ":name"',
+ 'piggy_bank' => 'Piggy bank',
+ 'new_piggy_bank' => 'Create new piggy bank',
+ 'store_piggy_bank' => 'Store new piggy bank',
+ 'account_status' => 'Account status',
+ 'left_for_piggy_banks' => 'Left for piggy banks',
+ 'sum_of_piggy_banks' => 'Sum of piggy banks',
+ 'saved_so_far' => 'Saved so far',
+ 'left_to_save' => 'Left to save',
+ 'add_money_to_piggy_title' => 'Add money to piggy bank ":name"',
+ 'remove_money_from_piggy_title' => 'Remove money from piggy bank ":name"',
+ 'add' => 'Add',
+ 'remove' => 'Remove',
+ 'max_amount_add' => 'The maximum amount you can add is',
+ 'max_amount_remove' => 'The maximum amount you can remove is',
+ 'update_piggy_button' => 'Update piggy bank',
+ 'update_piggy_title' => 'Update piggy bank ":name"',
+ 'details' => 'Details',
+ 'events' => 'Events',
+ 'target_amount' => 'Target amount',
+ 'start_date' => 'Start date',
+ 'target_date' => 'Target date',
+ 'no_target_date' => 'No target date',
+ 'todo' => 'to do',
+ 'table' => 'Table',
+ 'piggy_bank_not_exists' => 'Piggy bank no longer exists.',
+ 'add_any_amount_to_piggy' => 'Add money to this piggy bank to reach your target of :amount.',
+ 'add_set_amount_to_piggy' => 'Add :amount to fill this piggy bank on :date',
+ 'delete_piggy_bank' => 'Delete piggy bank ":name"',
// tags
- 'regular_tag' => 'Just a regular tag.',
- 'balancing_act' => 'The tag takes at most two transactions; an expense and a transfer. They\'ll balance each other out.',
- 'advance_payment' => 'The tag accepts one expense and any number of deposits aimed to repay the original expense.',
- 'delete_tag' => 'Delete tag ":tag"',
- 'new_tag' => 'Make new tag',
- 'edit_tag' => 'Edit tag ":tag"',
- 'no_year' => 'No year set',
- 'no_month' => 'No month set',
- 'tag_title_nothing' => 'Default tags',
- 'tag_title_balancingAct' => 'Balancing act tags',
- 'tag_title_advancePayment' => 'Advance payment tags',
- 'tags_introduction' => 'Usually tags are singular words, designed to quickly band items together using things like expensive, bill or for-party. In Firefly III, tags can have more properties such as a date, description and location. This allows you to join transactions together in a more meaningful way. For example, you could make a tag called Christmas dinner with friends and add information about the restaurant. Such tags are "singular", you would only use them for a single occasion, perhaps with multiple transactions.',
- 'tags_group' => 'Tags group transactions together, which makes it possible to store reimbursements (in case you front money for others) and other "balancing acts" where expenses are summed up (the payments on your new TV) or where expenses and deposits are cancelling each other out (buying something with saved money). It\'s all up to you. Using tags the old-fashioned way is of course always possible.',
- 'tags_start' => 'Create a tag to get started or enter tags when creating new transactions.',
+ 'regular_tag' => 'Just a regular tag.',
+ 'balancing_act' => 'The tag takes at most two transactions; an expense and a transfer. They\'ll balance each other out.',
+ 'advance_payment' => 'The tag accepts one expense and any number of deposits aimed to repay the original expense.',
+ 'delete_tag' => 'Delete tag ":tag"',
+ 'new_tag' => 'Make new tag',
+ 'edit_tag' => 'Edit tag ":tag"',
+ 'no_year' => 'No year set',
+ 'no_month' => 'No month set',
+ 'tag_title_nothing' => 'Default tags',
+ 'tag_title_balancingAct' => 'Balancing act tags',
+ 'tag_title_advancePayment' => 'Advance payment tags',
+ 'tags_introduction' => 'Usually tags are singular words, designed to quickly band items together using things like expensive, bill or for-party. In Firefly III, tags can have more properties such as a date, description and location. This allows you to join transactions together in a more meaningful way. For example, you could make a tag called Christmas dinner with friends and add information about the restaurant. Such tags are "singular", you would only use them for a single occasion, perhaps with multiple transactions.',
+ 'tags_group' => 'Tags group transactions together, which makes it possible to store reimbursements (in case you front money for others) and other "balancing acts" where expenses are summed up (the payments on your new TV) or where expenses and deposits are cancelling each other out (buying something with saved money). It\'s all up to you. Using tags the old-fashioned way is of course always possible.',
+ 'tags_start' => 'Create a tag to get started or enter tags when creating new transactions.',
];
diff --git a/resources/lang/en_US/form.php b/resources/lang/en_US/form.php
index d1d398ebc2..5361c8daac 100644
--- a/resources/lang/en_US/form.php
+++ b/resources/lang/en_US/form.php
@@ -1,4 +1,12 @@
'Revenue account',
'amount' => 'Amount',
'date' => 'Date',
+ 'interest_date' => 'Interest date',
+ 'book_date' => 'Book date',
+ 'process_date' => 'Processing date',
'category' => 'Category',
'tags' => 'Tags',
'deletePermanently' => 'Delete permanently',
@@ -47,6 +58,7 @@ return [
'symbol' => 'Symbol',
'code' => 'Code',
'iban' => 'IBAN',
+ 'accountNumber' => 'Account number',
'csv' => 'CSV file',
'has_headers' => 'Headers',
'date_format' => 'Date format',
@@ -70,40 +82,44 @@ return [
'size' => 'Size',
'trigger' => 'Trigger',
'stop_processing' => 'Stop processing',
-
- 'csv_comma' => 'A comma (,)',
- 'csv_semicolon' => 'A semicolon (;)',
- 'csv_tab' => 'A tab (invisible)',
-
-
- 'delete_account' => 'Delete account ":name"',
- 'delete_bill' => 'Delete bill ":name"',
- 'delete_budget' => 'Delete budget ":name"',
- 'delete_category' => 'Delete category ":name"',
- 'delete_currency' => 'Delete currency ":name"',
- 'delete_journal' => 'Delete transaction with description ":description"',
- 'delete_attachment' => 'Delete attachment ":name"',
- 'delete_rule' => 'Delete rule ":title"',
- 'delete_rule_group' => 'Delete rule group ":title"',
-
- 'attachment_areYouSure' => 'Are you sure you want to delete the attachment named ":name"?',
- 'account_areYouSure' => 'Are you sure you want to delete the account named ":name"?',
- 'bill_areYouSure' => 'Are you sure you want to delete the bill named ":name"?',
- 'rule_areYouSure' => 'Are you sure you want to delete the rule titled ":title"?',
- 'ruleGroup_areYouSure' => 'Are you sure you want to delete the rule group titled ":title"?',
- 'budget_areYouSure' => 'Are you sure you want to delete the budget named ":name"?',
- 'category_areYouSure' => 'Are you sure you want to delete the category named ":name"?',
- 'currency_areYouSure' => 'Are you sure you want to delete the currency named ":name"?',
- 'piggyBank_areYouSure' => 'Are you sure you want to delete the piggy bank named ":name"?',
- 'journal_areYouSure' => 'Are you sure you want to delete the transaction described ":description"?',
- 'tag_areYouSure' => 'Are you sure you want to delete the tag ":tag"?',
-
- 'permDeleteWarning' => 'Deleting stuff from Firely is permanent and cannot be undone.',
- 'also_delete_transactions' => 'The only transaction connected to this account will be deleted as well.|All :count transactions connected to this account will be deleted as well.',
- 'also_delete_rules' => 'The only rule connected to this rule group will be deleted as well.|All :count rules connected to this rule group will be deleted as well.',
- 'also_delete_piggyBanks' => 'The only piggy bank connected to this account will be deleted as well.|All :count piggy bank connected to this account will be deleted as well.',
- 'bill_keep_transactions' => 'The only transaction connected to this bill will not be deleted.|All :count transactions connected to this bill will spared deletion.',
- 'budget_keep_transactions' => 'The only transaction connected to this budget will not be deleted.|All :count transactions connected to this budget will spared deletion.',
- 'category_keep_transactions' => 'The only transaction connected to this category will not be deleted.|All :count transactions connected to this category will spared deletion.',
- 'tag_keep_transactions' => 'The only transaction connected to this tag will not be deleted.|All :count transactions connected to this tag will spared deletion.',
+ 'start_date' => 'Start of range',
+ 'end_date' => 'End of range',
+ 'export_start_range' => 'Start of export range',
+ 'export_end_range' => 'End of export range',
+ 'export_format' => 'File format',
+ 'include_attachments' => 'Include uploaded attachments',
+ 'include_config' => 'Include configuration file',
+ 'include_old_uploads' => 'Include imported data',
+ 'accounts' => 'Export transactions from these accounts',
+ 'csv_comma' => 'A comma (,)',
+ 'csv_semicolon' => 'A semicolon (;)',
+ 'csv_tab' => 'A tab (invisible)',
+ 'delete_account' => 'Delete account ":name"',
+ 'delete_bill' => 'Delete bill ":name"',
+ 'delete_budget' => 'Delete budget ":name"',
+ 'delete_category' => 'Delete category ":name"',
+ 'delete_currency' => 'Delete currency ":name"',
+ 'delete_journal' => 'Delete transaction with description ":description"',
+ 'delete_attachment' => 'Delete attachment ":name"',
+ 'delete_rule' => 'Delete rule ":title"',
+ 'delete_rule_group' => 'Delete rule group ":title"',
+ 'attachment_areYouSure' => 'Are you sure you want to delete the attachment named ":name"?',
+ 'account_areYouSure' => 'Are you sure you want to delete the account named ":name"?',
+ 'bill_areYouSure' => 'Are you sure you want to delete the bill named ":name"?',
+ 'rule_areYouSure' => 'Are you sure you want to delete the rule titled ":title"?',
+ 'ruleGroup_areYouSure' => 'Are you sure you want to delete the rule group titled ":title"?',
+ 'budget_areYouSure' => 'Are you sure you want to delete the budget named ":name"?',
+ 'category_areYouSure' => 'Are you sure you want to delete the category named ":name"?',
+ 'currency_areYouSure' => 'Are you sure you want to delete the currency named ":name"?',
+ 'piggyBank_areYouSure' => 'Are you sure you want to delete the piggy bank named ":name"?',
+ 'journal_areYouSure' => 'Are you sure you want to delete the transaction described ":description"?',
+ 'tag_areYouSure' => 'Are you sure you want to delete the tag ":tag"?',
+ 'permDeleteWarning' => 'Deleting stuff from Firely is permanent and cannot be undone.',
+ 'also_delete_transactions' => 'The only transaction connected to this account will be deleted as well.|All :count transactions connected to this account will be deleted as well.',
+ 'also_delete_rules' => 'The only rule connected to this rule group will be deleted as well.|All :count rules connected to this rule group will be deleted as well.',
+ 'also_delete_piggyBanks' => 'The only piggy bank connected to this account will be deleted as well.|All :count piggy bank connected to this account will be deleted as well.',
+ 'bill_keep_transactions' => 'The only transaction connected to this bill will not be deleted.|All :count transactions connected to this bill will spared deletion.',
+ 'budget_keep_transactions' => 'The only transaction connected to this budget will not be deleted.|All :count transactions connected to this budget will spared deletion.',
+ 'category_keep_transactions' => 'The only transaction connected to this category will not be deleted.|All :count transactions connected to this category will spared deletion.',
+ 'tag_keep_transactions' => 'The only transaction connected to this tag will not be deleted.|All :count transactions connected to this tag will spared deletion.',
];
diff --git a/resources/lang/en_US/help.php b/resources/lang/en_US/help.php
index 358db49713..4f5b30adc1 100644
--- a/resources/lang/en_US/help.php
+++ b/resources/lang/en_US/help.php
@@ -1,25 +1,31 @@
'Welcome to Firefly III',
- 'main-content-text' => 'Do yourself a favor and follow this short guide to make sure you know your way around.',
- 'sidebar-toggle-title' => 'Sidebar to create stuff',
- 'sidebar-toggle-text' => 'Hidden under the plus icon are all the buttons to create new stuff. Accounts, transactions, everything!',
- 'account-menu-title' => 'All your accounts',
- 'account-menu-text' => 'Here you can find all the accounts you\'ve made.',
- 'budget-menu-title' => 'Budgets',
- 'budget-menu-text' => 'Use this page to organise your finances and limit spending.',
- 'report-menu-title' => 'Reports',
- 'report-menu-text' => 'Check this out when you want a solid overview of your fiances.',
- 'transaction-menu-title' => 'Transactions',
- 'transaction-menu-text' => 'All transactions you\'ve created can be found here.',
- 'option-menu-title' => 'Options',
- 'option-menu-text' => 'This is pretty self-explanatory.',
- 'main-content-end-title' => 'The end!',
- 'main-content-end-text' => 'Remember that every page has a small question mark at the right top. Click it to get help about the page you\'re on.',
-
-
+ 'main-content-title' => 'Welcome to Firefly III',
+ 'main-content-text' => 'Do yourself a favor and follow this short guide to make sure you know your way around.',
+ 'sidebar-toggle-title' => 'Sidebar to create stuff',
+ 'sidebar-toggle-text' => 'Hidden under the plus icon are all the buttons to create new stuff. Accounts, transactions, everything!',
+ 'account-menu-title' => 'All your accounts',
+ 'account-menu-text' => 'Here you can find all the accounts you\'ve made.',
+ 'budget-menu-title' => 'Budgets',
+ 'budget-menu-text' => 'Use this page to organise your finances and limit spending.',
+ 'report-menu-title' => 'Reports',
+ 'report-menu-text' => 'Check this out when you want a solid overview of your fiances.',
+ 'transaction-menu-title' => 'Transactions',
+ 'transaction-menu-text' => 'All transactions you\'ve created can be found here.',
+ 'option-menu-title' => 'Options',
+ 'option-menu-text' => 'This is pretty self-explanatory.',
+ 'main-content-end-title' => 'The end!',
+ 'main-content-end-text' => 'Remember that every page has a small question mark at the right top. Click it to get help about the page you\'re on.',
'index' => 'index',
'home' => 'home',
'accounts-index' => 'accounts.index',
diff --git a/resources/lang/en_US/list.php b/resources/lang/en_US/list.php
index 4bc0b61bc9..29ebb0b6ca 100644
--- a/resources/lang/en_US/list.php
+++ b/resources/lang/en_US/list.php
@@ -1,6 +1,11 @@
'Name',
@@ -19,6 +24,9 @@ return [
'description' => 'Description',
'amount' => 'Amount',
'date' => 'Date',
+ 'interest_date' => 'Interest date',
+ 'book_date' => 'Book date',
+ 'process_date' => 'Processing date',
'from' => 'From',
'to' => 'To',
'budget' => 'Budget',
diff --git a/resources/lang/en_US/pagination.php b/resources/lang/en_US/pagination.php
index fcab34b253..d65fb9c5c0 100644
--- a/resources/lang/en_US/pagination.php
+++ b/resources/lang/en_US/pagination.php
@@ -1,19 +1,13 @@
'« Previous',
'next' => 'Next »',
-
];
diff --git a/resources/lang/en_US/passwords.php b/resources/lang/en_US/passwords.php
index 125f093fa8..8690468e9e 100644
--- a/resources/lang/en_US/passwords.php
+++ b/resources/lang/en_US/passwords.php
@@ -1,22 +1,17 @@
"Passwords must be at least six characters and match the confirmation.",
- "user" => "We can't find a user with that e-mail address.",
- "token" => "This password reset token is invalid.",
- "sent" => "We have e-mailed your password reset link!",
- "reset" => "Your password has been reset!",
+ 'password' => 'Passwords must be at least six characters and match the confirmation.',
+ 'user' => 'We can\'t find a user with that e-mail address.',
+ 'token' => 'This password reset token is invalid.',
+ 'sent' => 'We have e-mailed your password reset link!',
+ 'reset' => 'Your password has been reset!',
'blocked' => 'Nice try though.',
-
];
diff --git a/resources/lang/en_US/validation.php b/resources/lang/en_US/validation.php
index 88e58d3a19..7889d6d01f 100644
--- a/resources/lang/en_US/validation.php
+++ b/resources/lang/en_US/validation.php
@@ -1,69 +1,79 @@
'This value is invalid for the selected trigger.',
- 'rule_action_value' => 'This value is invalid for the selected action.',
- 'invalid_domain' => 'Due to security constraints, you cannot register from this domain.',
- 'file_already_attached' => 'Uploaded file ":name" is already attached to this object.',
- 'file_attached' => 'Succesfully uploaded file ":name".',
- 'file_invalid_mime' => 'File ":name" is of type ":mime" which is not accepted as a new upload.',
- 'file_too_large' => 'File ":name" is too large.',
- "accepted" => "The :attribute must be accepted.",
- "active_url" => "The :attribute is not a valid URL.",
- "after" => "The :attribute must be a date after :date.",
- "alpha" => "The :attribute may only contain letters.",
- "alpha_dash" => "The :attribute may only contain letters, numbers, and dashes.",
- "alpha_num" => "The :attribute may only contain letters and numbers.",
- "array" => "The :attribute must be an array.",
- "unique_for_user" => "There already is an entry with this :attribute.",
- "before" => "The :attribute must be a date before :date.",
- 'unique_object_for_user' => 'This name is already in use',
- 'unique_account_for_user' => 'This account name is already in use',
- "between.numeric" => "The :attribute must be between :min and :max.",
- "between.file" => "The :attribute must be between :min and :max kilobytes.",
- "between.string" => "The :attribute must be between :min and :max characters.",
- "between.array" => "The :attribute must have between :min and :max items.",
- "boolean" => "The :attribute field must be true or false.",
- "confirmed" => "The :attribute confirmation does not match.",
- "date" => "The :attribute is not a valid date.",
- "date_format" => "The :attribute does not match the format :format.",
- "different" => "The :attribute and :other must be different.",
- "digits" => "The :attribute must be :digits digits.",
- "digits_between" => "The :attribute must be between :min and :max digits.",
- "email" => "The :attribute must be a valid email address.",
- "filled" => "The :attribute field is required.",
- "exists" => "The selected :attribute is invalid.",
- "image" => "The :attribute must be an image.",
- "in" => "The selected :attribute is invalid.",
- "integer" => "The :attribute must be an integer.",
- "ip" => "The :attribute must be a valid IP address.",
- 'json' => 'The :attribute must be a valid JSON string.',
- "max.numeric" => "The :attribute may not be greater than :max.",
- "max.file" => "The :attribute may not be greater than :max kilobytes.",
- "max.string" => "The :attribute may not be greater than :max characters.",
- "max.array" => "The :attribute may not have more than :max items.",
- "mimes" => "The :attribute must be a file of type: :values.",
- "min.numeric" => "The :attribute must be at least :min.",
- "min.file" => "The :attribute must be at least :min kilobytes.",
- "min.string" => "The :attribute must be at least :min characters.",
- "min.array" => "The :attribute must have at least :min items.",
- "not_in" => "The selected :attribute is invalid.",
- "numeric" => "The :attribute must be a number.",
- "regex" => "The :attribute format is invalid.",
- "required" => "The :attribute field is required.",
- "required_if" => "The :attribute field is required when :other is :value.",
- 'required_unless' => 'The :attribute field is required unless :other is in :values.',
- "required_with" => "The :attribute field is required when :values is present.",
- "required_with_all" => "The :attribute field is required when :values is present.",
- "required_without" => "The :attribute field is required when :values is not present.",
- "required_without_all" => "The :attribute field is required when none of :values are present.",
- "same" => "The :attribute and :other must match.",
- "size.numeric" => "The :attribute must be :size.",
- "size.file" => "The :attribute must be :size kilobytes.",
- "size.string" => "The :attribute must be :size characters.",
- "size.array" => "The :attribute must contain :size items.",
- "unique" => "The :attribute has already been taken.",
- 'string' => 'The :attribute must be a string.',
- "url" => "The :attribute format is invalid.",
- "timezone" => "The :attribute must be a valid zone.",
+ 'iban' => 'This is not a valid IBAN.',
+ 'unique_account_number_for_user' => 'It looks like this account number is already in use.',
+ 'rule_trigger_value' => 'This value is invalid for the selected trigger.',
+ 'rule_action_value' => 'This value is invalid for the selected action.',
+ 'invalid_domain' => 'Due to security constraints, you cannot register from this domain.',
+ 'file_already_attached' => 'Uploaded file ":name" is already attached to this object.',
+ 'file_attached' => 'Succesfully uploaded file ":name".',
+ 'file_invalid_mime' => 'File ":name" is of type ":mime" which is not accepted as a new upload.',
+ 'file_too_large' => 'File ":name" is too large.',
+ 'accepted' => 'The :attribute must be accepted.',
+ 'active_url' => 'The :attribute is not a valid URL.',
+ 'after' => 'The :attribute must be a date after :date.',
+ 'alpha' => 'The :attribute may only contain letters.',
+ 'alpha_dash' => 'The :attribute may only contain letters, numbers, and dashes.',
+ 'alpha_num' => 'The :attribute may only contain letters and numbers.',
+ 'array' => 'The :attribute must be an array.',
+ 'unique_for_user' => 'There already is an entry with this :attribute.',
+ 'before' => 'The :attribute must be a date before :date.',
+ 'unique_object_for_user' => 'This name is already in use',
+ 'unique_account_for_user' => 'This account name is already in use',
+ 'between.numeric' => 'The :attribute must be between :min and :max.',
+ 'between.file' => 'The :attribute must be between :min and :max kilobytes.',
+ 'between.string' => 'The :attribute must be between :min and :max characters.',
+ 'between.array' => 'The :attribute must have between :min and :max items.',
+ 'boolean' => 'The :attribute field must be true or false.',
+ 'confirmed' => 'The :attribute confirmation does not match.',
+ 'date' => 'The :attribute is not a valid date.',
+ 'date_format' => 'The :attribute does not match the format :format.',
+ 'different' => 'The :attribute and :other must be different.',
+ 'digits' => 'The :attribute must be :digits digits.',
+ 'digits_between' => 'The :attribute must be between :min and :max digits.',
+ 'email' => 'The :attribute must be a valid email address.',
+ 'filled' => 'The :attribute field is required.',
+ 'exists' => 'The selected :attribute is invalid.',
+ 'image' => 'The :attribute must be an image.',
+ 'in' => 'The selected :attribute is invalid.',
+ 'integer' => 'The :attribute must be an integer.',
+ 'ip' => 'The :attribute must be a valid IP address.',
+ 'json' => 'The :attribute must be a valid JSON string.',
+ 'max.numeric' => 'The :attribute may not be greater than :max.',
+ 'max.file' => 'The :attribute may not be greater than :max kilobytes.',
+ 'max.string' => 'The :attribute may not be greater than :max characters.',
+ 'max.array' => 'The :attribute may not have more than :max items.',
+ 'mimes' => 'The :attribute must be a file of type: :values.',
+ 'min.numeric' => 'The :attribute must be at least :min.',
+ 'min.file' => 'The :attribute must be at least :min kilobytes.',
+ 'min.string' => 'The :attribute must be at least :min characters.',
+ 'min.array' => 'The :attribute must have at least :min items.',
+ 'not_in' => 'The selected :attribute is invalid.',
+ 'numeric' => 'The :attribute must be a number.',
+ 'regex' => 'The :attribute format is invalid.',
+ 'required' => 'The :attribute field is required.',
+ 'required_if' => 'The :attribute field is required when :other is :value.',
+ 'required_unless' => 'The :attribute field is required unless :other is in :values.',
+ 'required_with' => 'The :attribute field is required when :values is present.',
+ 'required_with_all' => 'The :attribute field is required when :values is present.',
+ 'required_without' => 'The :attribute field is required when :values is not present.',
+ 'required_without_all' => 'The :attribute field is required when none of :values are present.',
+ 'same' => 'The :attribute and :other must match.',
+ 'size.numeric' => 'The :attribute must be :size.',
+ 'size.file' => 'The :attribute must be :size kilobytes.',
+ 'size.string' => 'The :attribute must be :size characters.',
+ 'size.array' => 'The :attribute must contain :size items.',
+ 'unique' => 'The :attribute has already been taken.',
+ 'string' => 'The :attribute must be a string.',
+ 'url' => 'The :attribute format is invalid.',
+ 'timezone' => 'The :attribute must be a valid zone.',
+ '2fa_code' => 'The :attribute field is invalid.',
];
diff --git a/resources/lang/fr_FR/breadcrumbs.php b/resources/lang/fr_FR/breadcrumbs.php
old mode 100644
new mode 100755
index 9de636cc33..62e2727e55
--- a/resources/lang/fr_FR/breadcrumbs.php
+++ b/resources/lang/fr_FR/breadcrumbs.php
@@ -1,60 +1,45 @@
'Accueil',
-
- // accounts
'cash_accounts' => 'Cash accounts',
'edit_account' => 'Editer le compte : ":name"',
-
- // currencies
'edit_currency' => 'Editer la devise : ";name"',
'delete_currency' => 'Supprimer la devise ":name"',
-
- // piggy banks
'newPiggyBank' => 'Create a new piggy bank',
'edit_piggyBank' => 'Edit piggy bank ":name"',
-
- // top menu
'preferences' => 'Preferences',
'profile' => 'Profil',
'changePassword' => 'Modifier le mot de passe',
-
- // bills
'bills' => 'Factures',
'newBill' => 'Nouvelle facture',
'edit_bill' => 'Editer la facture : ":name"',
'delete_bill' => 'Supprimer la facture ":name"',
-
- // reports
'reports' => 'Rapport',
'monthly_report' => 'Rapport mensuel pour :date',
'monthly_report_shared' => 'Rapport mensuel pour :date (avec les comptes joints)',
'yearly_report' => 'Rapport annuel pour :date',
'yearly_report_shared' => 'Rapport annuel pour :date (avec les comptes joints)',
'budget_report' => 'Rapport budgetaire pour :date',
-
- // search
'searchResult' => 'Resultat de recherche pour ":query"',
-
- // transaction lists.
'withdrawal_list' => 'Dépenses',
'deposit_list' => 'Revenue, Salaire et depots ',
'transfer_list' => 'Transferts',
'transfers_list' => 'Transferts',
-
- // create transactions
'create_withdrawal' => 'Creer un nouveau retrait',
'create_deposit' => 'Create new deposit',
'create_transfer' => 'Creer un nouveau transfert',
-
- // edit transactions
'edit_journal' => 'Editer la transaction ":description"',
'delete_journal' => 'Supprimer la transaction ":description"',
-
- // tags
'tags' => 'Tags',
'createTag' => 'Créer un nouveau tag',
'edit_tag' => 'Editer le tag ":tag"',
'delete_tag' => 'Supprimer le tag ":tag"',
-
];
diff --git a/resources/lang/fr_FR/config.php b/resources/lang/fr_FR/config.php
old mode 100644
new mode 100755
index 6aa208d339..8d326a4ad2
--- a/resources/lang/fr_FR/config.php
+++ b/resources/lang/fr_FR/config.php
@@ -1,8 +1,20 @@
'fr, French, fr_FR, fr_FR.utf8',
- 'month' => '%B %Y',
- 'month_and_day' => '%e %B %Y',
-
+ 'locale' => 'fr, French, fr_FR, fr_FR.utf8',
+ 'month' => '%B %Y',
+ 'month_and_day' => '%e %B %Y',
+ 'date_time' => '%B %e, %Y, @ %T',
+ 'specific_day' => '%e %B %Y',
+ 'week_in_year' => 'Week %W, %Y',
+ 'quarter_of_year' => '%B %Y',
+ 'year' => '%Y',
+ 'half_year' => '%B %Y',
];
diff --git a/resources/lang/fr_FR/firefly.php b/resources/lang/fr_FR/firefly.php
old mode 100644
new mode 100755
index 502db22d64..6b32e593ca
--- a/resources/lang/fr_FR/firefly.php
+++ b/resources/lang/fr_FR/firefly.php
@@ -1,111 +1,167 @@
'Cette langue n\'est pas encore complètement traduite',
- 'test' => 'Vous avez choisi Anglais',
- 'close' => 'Fermer',
- 'pleaseHold' => 'Veuillew patienter...',
- 'actions' => 'Actions',
- 'edit' => 'Editer',
- 'delete' => 'Supprimer',
- 'welcomeBack' => 'What\'s playing?',
- 'everything' => 'Tout',
- 'customRange' => 'Plage personnalisée',
- 'apply' => 'Appliquer',
- 'cancel' => 'Annuler',
- 'from' => 'Depuis',
- 'to' => 'To',
- 'total_sum' => 'Montant total ',
- 'period_sum' => 'Somme pour la période',
- 'showEverything' => 'Tout Afficher',
- 'never' => 'Jamais',
- 'search_results_for' => 'Résultats de recherche pour ":query"',
- 'bounced_error' => 'Le message envoyé à :email a été rejeté, donc pas d\'accès pour vous.',
- 'deleted_error' => 'These credentials do not match our records.',
- 'general_blocked_error' => 'Your account has been disabled, so you cannot login.',
- 'removed_amount' => 'Supprimé :amount',
- 'added_amount' => 'Ajouté :amount',
- 'asset_account_role_help' => 'Any extra options resulting from your choice can be set later.',
- 'Opening balance' => 'Solde initial',
- 'create_new_stuff' => 'Create new stuff',
- 'new_withdrawal' => 'Nouveau retrait',
- 'new_deposit' => 'Nouveau dépôt',
- 'new_transfer' => 'Nouveau transfert',
- 'new_asset_account' => 'New asset account',
- 'new_expense_account' => 'New expense account',
- 'new_revenue_account' => 'Nouveau compte de recettes',
- 'new_budget' => 'Nouveau budget',
- 'new_bill' => 'Nouvelle facture',
+ 'language_incomplete' => 'Cette langue n\'est pas encore complètement traduite',
+ 'test' => 'Vous avez choisi Anglais',
+ 'close' => 'Fermer',
+ 'pleaseHold' => 'Veuillew patienter...',
+ 'actions' => 'Actions',
+ 'edit' => 'Editer',
+ 'delete' => 'Supprimer',
+ 'welcomeBack' => 'What\'s playing?',
+ 'everything' => 'Tout',
+ 'customRange' => 'Plage personnalisée',
+ 'apply' => 'Appliquer',
+ 'cancel' => 'Annuler',
+ 'from' => 'Depuis',
+ 'to' => 'To',
+ 'total_sum' => 'Montant total ',
+ 'period_sum' => 'Somme pour la période',
+ 'showEverything' => 'Tout Afficher',
+ 'never' => 'Jamais',
+ 'search_results_for' => 'Résultats de recherche pour ":query"',
+ 'bounced_error' => 'Le message envoyé à :email a été rejeté, donc pas d\'accès pour vous.',
+ 'deleted_error' => 'These credentials do not match our records.',
+ 'general_blocked_error' => 'Your account has been disabled, so you cannot login.',
+ 'removed_amount' => 'Supprimé :amount',
+ 'added_amount' => 'Ajouté :amount',
+ 'asset_account_role_help' => 'Any extra options resulting from your choice can be set later.',
+ 'Opening balance' => 'Solde initial',
+ 'create_new_stuff' => 'Create new stuff',
+ 'new_withdrawal' => 'Nouveau retrait',
+ 'new_deposit' => 'Nouveau dépôt',
+ 'new_transfer' => 'Nouveau transfert',
+ 'new_asset_account' => 'New asset account',
+ 'new_expense_account' => 'New expense account',
+ 'new_revenue_account' => 'Nouveau compte de recettes',
+ 'new_budget' => 'Nouveau budget',
+ 'new_bill' => 'Nouvelle facture',
+ 'block_account_logout' => 'You have been logged out. Blocked accounts cannot use this site. Did you register with a valid email address?',
+ 'flash_success' => 'Success!',
+ 'flash_info' => 'Message',
+ 'flash_warning' => 'Warning!',
+ 'flash_error' => 'Error!',
+ 'flash_info_multiple' => 'There is one message|There are :count messages',
+ 'flash_error_multiple' => 'There is one error|There are :count errors',
+ 'net_worth' => 'Net worth',
+
+ // export data:
+ 'import_and_export' => 'Import and export',
+ 'export_data' => 'Export data',
+ 'export_data_intro' => 'For backup purposes, when migrating to another system or when migrating to another Firefly III installation.',
+ 'export_format' => 'Export format',
+ 'export_format_csv' => 'Comma separated values (CSV file)',
+ 'export_format_mt940' => 'MT940 compatible format',
+ 'export_included_accounts' => 'Export transactions from these accounts',
+ 'include_config_help' => 'For easy re-import into Firefly III',
+ 'include_old_uploads_help' => 'Firefly III does not throw away the original CSV files you have imported in the past. You can include them in your export.',
+ 'do_export' => 'Export',
+ 'export_status_never_started' => 'The export has not started yet',
+ 'export_status_make_exporter' => 'Creating exporter thing...',
+ 'export_status_collecting_journals' => 'Collecting your transactions...',
+ 'export_status_collected_journals' => 'Collected your transactions!',
+ 'export_status_converting_to_export_format' => 'Converting your transactions...',
+ 'export_status_converted_to_export_format' => 'Converted your transactions!',
+ 'export_status_creating_journal_file' => 'Creating the export file...',
+ 'export_status_created_journal_file' => 'Created the export file!',
+ 'export_status_collecting_attachments' => 'Collecting all your attachments...',
+ 'export_status_collected_attachments' => 'Collected all your attachments!',
+ 'export_status_collecting_old_uploads' => 'Collecting all your previous uploads...',
+ 'export_status_collected_old_uploads' => 'Collected all your previous uploads!',
+ 'export_status_creating_config_file' => 'Creating a configuration file...',
+ 'export_status_created_config_file' => 'Created a configuration file!',
+ 'export_status_creating_zip_file' => 'Creating a zip file...',
+ 'export_status_created_zip_file' => 'Created a zip file!',
+ 'export_status_finished' => 'Export has succesfully finished! Yay!',
+ 'export_data_please_wait' => 'Please wait...',
+ 'attachment_explanation' => 'The file called \':attachment_name\' (#:attachment_id) was originally uploaded to :type \':description\' (#:journal_id) dated :date for the amount of :amount.',
// rules
- 'rules' => 'Rules',
- 'rules_explanation' => 'Here you can manage rules. Rules are triggered when a transaction is created or updated. Then, if the transaction has certain properties (called "triggers") Firefly will execute the "actions". Combined, you can make Firefly respond in a certain way to new transactions.',
- 'rule_name' => 'Name of rule',
- 'rule_triggers' => 'Rule triggers when',
- 'rule_actions' => 'Rule will',
- 'new_rule' => 'New rule',
- 'new_rule_group' => 'New rule group',
- 'rule_priority_up' => 'Give rule more priority',
- 'rule_priority_down' => 'Give rule less priority',
- 'make_new_rule_group' => 'Make new rule group',
- 'store_new_rule_group' => 'Store new rule group',
- 'created_new_rule_group' => 'New rule group ":title" stored!',
- 'updated_rule_group' => 'Successfully updated rule group ":title".',
- 'edit_rule_group' => 'Edit rule group ":title"',
- 'delete_rule_group' => 'Delete rule group ":title"',
- 'deleted_rule_group' => 'Deleted rule group ":title"',
- 'update_rule_group' => 'Update rule group',
- 'no_rules_in_group' => 'There are no rules in this group',
- 'move_rule_group_up' => 'Move rule group up',
- 'move_rule_group_down' => 'Move rule group down',
- 'save_rules_by_moving' => 'Save these rule(s) by moving them to another rule group:',
- 'make_new_rule' => 'Make new rule in rule group ":title"',
- 'rule_help_stop_processing' => 'When you check this box, later rules in this group will not be executed.',
- 'rule_help_active' => 'Inactive rules will never fire.',
- 'stored_new_rule' => 'Stored new rule with title ":title"',
- 'deleted_rule' => 'Deleted rule with title ":title"',
- 'store_new_rule' => 'Store new rule',
- 'updated_rule' => 'Updated rule with title ":title"',
- 'default_rule_group_name' => 'Default rules',
- 'default_rule_group_description' => 'All your rules not in a particular group.',
- 'default_rule_name' => 'Your first default rule',
- 'default_rule_description' => 'This rule is an example. You can safely delete it.',
- 'default_rule_trigger_description' => 'The Man Who Sold the World',
- 'default_rule_trigger_from_account' => 'David Bowie',
- 'default_rule_action_prepend' => 'Bought the world from ',
- 'default_rule_action_set_category' => 'Large expenses',
-
- 'trigger' => 'Trigger',
- 'trigger_value' => 'Trigger on value',
- 'stop_processing_other_triggers' => 'Stop processing other triggers',
- 'add_rule_trigger' => 'Add new trigger',
- 'action' => 'Action',
- 'action_value' => 'Action value',
- 'stop_executing_other_actions' => 'Stop executing other actions',
- 'add_rule_action' => 'Add new action',
- 'edit_rule' => 'Edit rule ":title"',
- 'update_rule' => 'Update rule',
+ 'rules' => 'Rules',
+ 'rules_explanation' => 'Here you can manage rules. Rules are triggered when a transaction is created or updated. Then, if the transaction has certain properties (called "triggers") Firefly will execute the "actions". Combined, you can make Firefly respond in a certain way to new transactions.',
+ 'rule_name' => 'Name of rule',
+ 'rule_triggers' => 'Rule triggers when',
+ 'rule_actions' => 'Rule will',
+ 'new_rule' => 'New rule',
+ 'new_rule_group' => 'New rule group',
+ 'rule_priority_up' => 'Give rule more priority',
+ 'rule_priority_down' => 'Give rule less priority',
+ 'make_new_rule_group' => 'Make new rule group',
+ 'store_new_rule_group' => 'Store new rule group',
+ 'created_new_rule_group' => 'New rule group ":title" stored!',
+ 'updated_rule_group' => 'Successfully updated rule group ":title".',
+ 'edit_rule_group' => 'Edit rule group ":title"',
+ 'delete_rule_group' => 'Delete rule group ":title"',
+ 'deleted_rule_group' => 'Deleted rule group ":title"',
+ 'update_rule_group' => 'Update rule group',
+ 'no_rules_in_group' => 'There are no rules in this group',
+ 'move_rule_group_up' => 'Move rule group up',
+ 'move_rule_group_down' => 'Move rule group down',
+ 'save_rules_by_moving' => 'Save these rule(s) by moving them to another rule group:',
+ 'make_new_rule' => 'Make new rule in rule group ":title"',
+ 'rule_help_stop_processing' => 'When you check this box, later rules in this group will not be executed.',
+ 'rule_help_active' => 'Inactive rules will never fire.',
+ 'stored_new_rule' => 'Stored new rule with title ":title"',
+ 'deleted_rule' => 'Deleted rule with title ":title"',
+ 'store_new_rule' => 'Store new rule',
+ 'updated_rule' => 'Updated rule with title ":title"',
+ 'default_rule_group_name' => 'Default rules',
+ 'default_rule_group_description' => 'All your rules not in a particular group.',
+ 'default_rule_name' => 'Your first default rule',
+ 'default_rule_description' => 'This rule is an example. You can safely delete it.',
+ 'default_rule_trigger_description' => 'The Man Who Sold the World',
+ 'default_rule_trigger_from_account' => 'David Bowie',
+ 'default_rule_action_prepend' => 'Bought the world from ',
+ 'default_rule_action_set_category' => 'Large expenses',
+ 'trigger' => 'Trigger',
+ 'trigger_value' => 'Trigger on value',
+ 'stop_processing_other_triggers' => 'Stop processing other triggers',
+ 'add_rule_trigger' => 'Add new trigger',
+ 'action' => 'Action',
+ 'action_value' => 'Action value',
+ 'stop_executing_other_actions' => 'Stop executing other actions',
+ 'add_rule_action' => 'Add new action',
+ 'edit_rule' => 'Edit rule ":title"',
+ 'delete_rule' => 'Delete rule ":title"',
+ 'update_rule' => 'Update rule',
+ 'test_rule_triggers' => 'See matching transactions',
+ 'warning_transaction_subset' => 'For performance reasons this list is limited to :max_num_transactions and may only show a subset of matching transactions',
+ 'warning_no_matching_transactions' => 'No matching transactions found. Please note that for performance reasons, only the last :num_transactions transactions have been checked.',
+ 'warning_no_valid_triggers' => 'No valid triggers provided.',
+ 'execute_on_existing_transactions' => 'Execute for existing transactions',
+ 'execute_on_existing_transactions_intro' => 'When a rule or group has been changed or added, you can execute it for existing transactions',
+ 'execute_on_existing_transactions_short' => 'Existing transactions',
+ 'executed_group_on_existing_transactions' => 'Executed group ":title" for existing transactions',
+ 'execute_group_on_existing_transactions' => 'Execute group ":title" for existing transactions',
+ 'include_transactions_from_accounts' => 'Include transactions from these accounts',
+ 'execute' => 'Execute',
// actions and triggers
- 'rule_trigger_user_action' => 'User action is ":trigger_value"',
- 'rule_trigger_from_account_starts' => 'Source account starts with ":trigger_value"',
- 'rule_trigger_from_account_ends' => 'Source account ends with ":trigger_value"',
- 'rule_trigger_from_account_is' => 'Source account is ":trigger_value"',
- 'rule_trigger_from_account_contains' => 'Source account contains ":trigger_value"',
- 'rule_trigger_to_account_starts' => 'Destination account starts with ":trigger_value"',
- 'rule_trigger_to_account_ends' => 'Destination account ends with ":trigger_value"',
- 'rule_trigger_to_account_is' => 'Destination account is ":trigger_value"',
- 'rule_trigger_to_account_contains' => 'Destination account contains ":trigger_value"',
- 'rule_trigger_transaction_type' => 'Transaction is of type ":trigger_value"',
- 'rule_trigger_amount_less' => 'Amount is less than :trigger_value',
- 'rule_trigger_amount_exactly' => 'Amount is :trigger_value',
- 'rule_trigger_amount_more' => 'Amount is more than :trigger_value',
- 'rule_trigger_description_starts' => 'Description starts with ":trigger_value"',
- 'rule_trigger_description_ends' => 'Description ends with ":trigger_value"',
- 'rule_trigger_description_contains' => 'Description contains ":trigger_value"',
- 'rule_trigger_description_is' => 'Description is ":trigger_value"',
-
+ 'rule_trigger_user_action' => 'User action is ":trigger_value"',
+ 'rule_trigger_from_account_starts' => 'Source account starts with ":trigger_value"',
+ 'rule_trigger_from_account_ends' => 'Source account ends with ":trigger_value"',
+ 'rule_trigger_from_account_is' => 'Source account is ":trigger_value"',
+ 'rule_trigger_from_account_contains' => 'Source account contains ":trigger_value"',
+ 'rule_trigger_to_account_starts' => 'Destination account starts with ":trigger_value"',
+ 'rule_trigger_to_account_ends' => 'Destination account ends with ":trigger_value"',
+ 'rule_trigger_to_account_is' => 'Destination account is ":trigger_value"',
+ 'rule_trigger_to_account_contains' => 'Destination account contains ":trigger_value"',
+ 'rule_trigger_transaction_type' => 'Transaction is of type ":trigger_value"',
+ 'rule_trigger_amount_less' => 'Amount is less than :trigger_value',
+ 'rule_trigger_amount_exactly' => 'Amount is :trigger_value',
+ 'rule_trigger_amount_more' => 'Amount is more than :trigger_value',
+ 'rule_trigger_description_starts' => 'Description starts with ":trigger_value"',
+ 'rule_trigger_description_ends' => 'Description ends with ":trigger_value"',
+ 'rule_trigger_description_contains' => 'Description contains ":trigger_value"',
+ 'rule_trigger_description_is' => 'Description is ":trigger_value"',
'rule_trigger_from_account_starts_choice' => 'Source account starts with..',
'rule_trigger_from_account_ends_choice' => 'Source account ends with..',
'rule_trigger_from_account_is_choice' => 'Source account is..',
@@ -122,486 +178,497 @@ return [
'rule_trigger_description_ends_choice' => 'Description ends with..',
'rule_trigger_description_contains_choice' => 'Description contains..',
'rule_trigger_description_is_choice' => 'Description is..',
-
- 'rule_trigger_store_journal' => 'When a journal is created',
- 'rule_trigger_update_journal' => 'When a journal is updated',
-
- 'rule_action_set_category' => 'Set category to ":action_value"',
- 'rule_action_clear_category' => 'Clear category',
- 'rule_action_set_budget' => 'Set budget to ":action_value"',
- 'rule_action_clear_budget' => 'Clear budget',
- 'rule_action_add_tag' => 'Add tag ":action_value"',
- 'rule_action_remove_tag' => 'Remove tag ":action_value"',
- 'rule_action_remove_all_tags' => 'Remove all tags',
- 'rule_action_set_description' => 'Set description to ":action_value"',
- 'rule_action_append_description' => 'Append description with ":action_value"',
- 'rule_action_prepend_description' => 'Prepend description with ":action_value"',
-
- 'rule_action_set_category_choice' => 'Set category to..',
- 'rule_action_clear_category_choice' => 'Clear any category',
- 'rule_action_set_budget_choice' => 'Set budget to..',
- 'rule_action_clear_budget_choice' => 'Clear any budget',
- 'rule_action_add_tag_choice' => 'Add tag..',
- 'rule_action_remove_tag_choice' => 'Remove tag..',
- 'rule_action_remove_all_tags_choice' => 'Remove all tags',
- 'rule_action_set_description_choice' => 'Set description to..',
- 'rule_action_append_description_choice' => 'Append description with..',
- 'rule_action_prepend_description_choice' => 'Prepend description with..',
+ 'rule_trigger_store_journal' => 'When a journal is created',
+ 'rule_trigger_update_journal' => 'When a journal is updated',
+ 'rule_action_set_category' => 'Set category to ":action_value"',
+ 'rule_action_clear_category' => 'Clear category',
+ 'rule_action_set_budget' => 'Set budget to ":action_value"',
+ 'rule_action_clear_budget' => 'Clear budget',
+ 'rule_action_add_tag' => 'Add tag ":action_value"',
+ 'rule_action_remove_tag' => 'Remove tag ":action_value"',
+ 'rule_action_remove_all_tags' => 'Remove all tags',
+ 'rule_action_set_description' => 'Set description to ":action_value"',
+ 'rule_action_append_description' => 'Append description with ":action_value"',
+ 'rule_action_prepend_description' => 'Prepend description with ":action_value"',
+ 'rule_action_set_category_choice' => 'Set category to..',
+ 'rule_action_clear_category_choice' => 'Clear any category',
+ 'rule_action_set_budget_choice' => 'Set budget to..',
+ 'rule_action_clear_budget_choice' => 'Clear any budget',
+ 'rule_action_add_tag_choice' => 'Add tag..',
+ 'rule_action_remove_tag_choice' => 'Remove tag..',
+ 'rule_action_remove_all_tags_choice' => 'Remove all tags',
+ 'rule_action_set_description_choice' => 'Set description to..',
+ 'rule_action_append_description_choice' => 'Append description with..',
+ 'rule_action_prepend_description_choice' => 'Prepend description with..',
// tags
- 'store_new_tag' => 'Créer un nouveau tag',
- 'update_tag' => 'Mettre à jour le tag',
- 'no_location_set' => 'Aucun emplacement défini.',
- 'meta_data' => 'Meta-données',
- 'location' => 'Emplacement',
+ 'store_new_tag' => 'Créer un nouveau tag',
+ 'update_tag' => 'Mettre à jour le tag',
+ 'no_location_set' => 'Aucun emplacement défini.',
+ 'meta_data' => 'Meta-données',
+ 'location' => 'Emplacement',
// preferences
- 'pref_home_screen_accounts' => 'Home screen accounts',
- 'pref_home_screen_accounts_help' => 'Which accounts should be displayed on the home page?',
- 'pref_budget_settings' => 'Paramètres de budget',
- 'pref_budget_settings_help' => 'What\'s the maximum amount of money a budget envelope may contain?',
- 'pref_view_range' => 'View range',
- 'pref_view_range_help' => 'Some charts are automatically grouped in periods. What period would you prefer?',
- 'pref_1D' => 'One day',
- 'pref_1W' => 'One week',
- 'pref_1M' => 'One month',
- 'pref_3M' => 'Three months (quarter)',
- 'pref_6M' => 'Six months',
- 'pref_languages' => 'Languages',
- 'pref_languages_help' => 'Firefly III supports several languages. Which one do you prefer?',
- 'pref_custom_fiscal_year' => 'Fiscal year settings',
- 'pref_custom_fiscal_year_label' => 'Enabled',
- 'pref_custom_fiscal_year_help' => 'In countries that use a financial year other than January 1 to December 31, you can switch this on and specify start / end days of the fiscal year',
- 'pref_fiscal_year_start_label' => 'Fiscal year start date',
- 'pref_save_settings' => 'Save settings',
+ 'pref_home_screen_accounts' => 'Home screen accounts',
+ 'pref_home_screen_accounts_help' => 'Which accounts should be displayed on the home page?',
+ 'pref_budget_settings' => 'Paramètres de budget',
+ 'pref_budget_settings_help' => 'What\'s the maximum amount of money a budget envelope may contain?',
+ 'pref_view_range' => 'View range',
+ 'pref_view_range_help' => 'Some charts are automatically grouped in periods. What period would you prefer?',
+ 'pref_1D' => 'One day',
+ 'pref_1W' => 'One week',
+ 'pref_1M' => 'One month',
+ 'pref_3M' => 'Three months (quarter)',
+ 'pref_6M' => 'Six months',
+ 'pref_languages' => 'Languages',
+ 'pref_languages_help' => 'Firefly III supports several languages. Which one do you prefer?',
+ 'pref_custom_fiscal_year' => 'Fiscal year settings',
+ 'pref_custom_fiscal_year_label' => 'Enabled',
+ 'pref_custom_fiscal_year_help' => 'In countries that use a financial year other than January 1 to December 31, you can switch this on and specify start / end days of the fiscal year',
+ 'pref_fiscal_year_start_label' => 'Fiscal year start date',
+ 'pref_two_factor_auth' => '2-step verification',
+ 'pref_two_factor_auth_help' => 'When you enable 2-step verification (also known as two-factor authentication), you add an extra layer of security to your account. You sign in with something you know (your password) and something you have (a verification code). Verification codes are generated by an application on your phone, such as Authy or Google Authenticator.',
+ 'pref_enable_two_factor_auth' => 'Enable 2-step verification',
+ 'pref_two_factor_auth_disabled' => '2-step verification code removed and disabled',
+ 'pref_two_factor_auth_remove_it' => 'Don\'t forget to remove the account from your authentication app!',
+ 'pref_two_factor_auth_code' => 'Verify code',
+ 'pref_two_factor_auth_code_help' => 'Scan the QR code with an application on your phone such as Authy or Google Authenticator and enter the generated code.',
+ 'pref_two_factor_auth_reset_code' => 'Reset verification code',
+ 'pref_two_factor_auth_remove_code' => 'Remove verification code',
+ 'pref_two_factor_auth_remove_will_disable' => '(this will also disable two-factor authentication)',
+ 'pref_save_settings' => 'Save settings',
// profile:
- 'change_your_password' => 'Change your password',
- 'delete_account' => 'Delete account',
- 'current_password' => 'Current password',
- 'new_password' => 'New password',
- 'new_password_again' => 'New password (again)',
- 'delete_your_account' => 'Delete your account',
- 'delete_your_account_help' => 'Deleting your account will also delete any accounts, transactions, anything you might have saved into Firefly III. It\'ll be GONE.',
- 'delete_your_account_password' => 'Enter your password to continue.',
- 'password' => 'Password',
- 'are_you_sure' => 'Are you sure? You cannot undo this.',
- 'delete_account_button' => 'DELETE your account',
- 'invalid_current_password' => 'Invalid current password!',
- 'password_changed' => 'Password changed!',
- 'should_change' => 'The idea is to change your password.',
- 'invalid_password' => 'Invalid password!',
-
+ 'change_your_password' => 'Change your password',
+ 'delete_account' => 'Delete account',
+ 'current_password' => 'Current password',
+ 'new_password' => 'New password',
+ 'new_password_again' => 'New password (again)',
+ 'delete_your_account' => 'Delete your account',
+ 'delete_your_account_help' => 'Deleting your account will also delete any accounts, transactions, anything you might have saved into Firefly III. It\'ll be GONE.',
+ 'delete_your_account_password' => 'Enter your password to continue.',
+ 'password' => 'Password',
+ 'are_you_sure' => 'Are you sure? You cannot undo this.',
+ 'delete_account_button' => 'DELETE your account',
+ 'invalid_current_password' => 'Invalid current password!',
+ 'password_changed' => 'Password changed!',
+ 'should_change' => 'The idea is to change your password.',
+ 'invalid_password' => 'Invalid password!',
// attachments
- 'nr_of_attachments' => 'One attachment|:count attachments',
- 'attachments' => 'Attachments',
- 'edit_attachment' => 'Edit attachment ":name"',
- 'update_attachment' => 'Update attachment',
- 'delete_attachment' => 'Delete attachment ":name"',
- 'attachment_deleted' => 'Deleted attachment ":name"',
- 'upload_max_file_size' => 'Maximum file size: :size',
+ 'nr_of_attachments' => 'One attachment|:count attachments',
+ 'attachments' => 'Attachments',
+ 'edit_attachment' => 'Edit attachment ":name"',
+ 'update_attachment' => 'Update attachment',
+ 'delete_attachment' => 'Delete attachment ":name"',
+ 'attachment_deleted' => 'Deleted attachment ":name"',
+ 'upload_max_file_size' => 'Maximum file size: :size',
// tour:
- 'prev' => 'Prev',
- 'next' => 'Next',
- 'end-tour' => 'End tour',
- 'pause' => 'Pause',
+ 'prev' => 'Prev',
+ 'next' => 'Next',
+ 'end-tour' => 'End tour',
+ 'pause' => 'Pause',
// transaction index
- 'title_expenses' => 'Expenses',
- 'title_withdrawal' => 'Expenses',
- 'title_revenue' => 'Revenue / income',
- 'title_deposit' => 'Revenue / income',
- 'title_transfer' => 'Transferts',
- 'title_transfers' => 'Transferts',
+ 'title_expenses' => 'Expenses',
+ 'title_withdrawal' => 'Expenses',
+ 'title_revenue' => 'Revenue / income',
+ 'title_deposit' => 'Revenue / income',
+ 'title_transfer' => 'Transferts',
+ 'title_transfers' => 'Transferts',
// csv import:
- 'csv_import' => 'Import CSV file',
- 'csv' => 'CSV',
- 'csv_index_title' => 'Upload and import a CSV file',
- 'csv_define_column_roles' => 'Define column roles',
- 'csv_map_values' => 'Map found values to existing values',
- 'csv_download_config' => 'Download CSV configuration file.',
- 'csv_index_text' => 'This form allows you to import a CSV file with transactions into Firefly. It is based on the excellent CSV importer made by the folks at Atlassian. Simply upload your CSV file and follow the instructions. If you would like to learn more, please click on the button at the top of this page.',
- 'csv_index_beta_warning' => 'This tool is very much in beta. Please proceed with caution',
- 'csv_header_help' => 'Check this box when your CSV file\'s first row consists of column names, not actual data',
- 'csv_date_help' => 'Date time format in your CSV. Follow the format like this page indicates. The default value will parse dates that look like this: :dateExample.',
- 'csv_csv_file_help' => 'Select the CSV file here. You can only upload one file at a time',
- 'csv_csv_config_file_help' => 'Select your CSV import configuration here. If you do not know what this is, ignore it. It will be explained later.',
- 'csv_upload_button' => 'Start importing CSV',
- 'csv_column_roles_title' => 'Define column roles',
- 'csv_column_roles_text' => 'Firefly does not know what each column means. You need to indicate what every column is. Please check out the example data if you\'re not sure yourself. Click on the question mark (top right of the page) to learn what each column means. If you want to map imported data onto existing data in Firefly, use the checkbox. The next step will show you what this button does.',
- 'csv_column_roles_table' => 'Column roles',
- 'csv_column' => 'CSV column',
- 'csv_column_name' => 'CSV column name',
- 'csv_column_example' => 'Column example data',
- 'csv_column_role' => 'Column contains?',
- 'csv_do_map_value' => 'Map value?',
- 'csv_continue' => 'Continue to the next step',
- 'csv_go_back' => 'Go back to the previous step',
- 'csv_map_title' => 'Map found values to existing values',
- 'csv_map_text' => 'This page allows you to map the values from the CSV file to existing entries in your database. This ensures that accounts and other things won\'t be created twice.',
- 'csv_field_value' => 'Field value from CSV',
- 'csv_field_mapped_to' => 'Must be mapped to...',
- 'csv_do_not_map' => 'Do not map this value',
- 'csv_download_config_title' => 'Download CSV configuration',
- 'csv_download_config_text' => 'Everything you\'ve just set up can be downloaded as a configuration file. Click the button to do so.',
- 'csv_more_information_text' => 'If the import fails, you can use this configuration file so you don\'t have to start all over again. But, if the import succeeds, it will be easier to upload similar CSV files.',
- 'csv_do_download_config' => 'Download configuration file.',
- 'csv_empty_description' => '(empty description)',
- 'csv_upload_form' => 'CSV upload form',
- 'csv_index_unsupported_warning' => 'The CSV importer is yet incapable of doing the following:',
- 'csv_unsupported_map' => 'The importer cannot map the column ":columnRole" to existing values in the database.',
- 'csv_unsupported_value' => 'The importer does not know how to handle values in columns marked as ":columnRole".',
- 'csv_cannot_store_value' => 'The importer has not reserved space for columns marked ":columnRole" and will be incapable of processing them.',
- 'csv_process_title' => 'CSV import finished!',
- 'csv_process_text' => 'The CSV importer has finished and has processed :rows rows',
- 'csv_row' => 'Row',
- 'csv_import_with_errors' => 'There was one error.|There were :errors errors.',
- 'csv_error_see_logs' => 'Check the log files to see details.',
- 'csv_process_new_entries' => 'Firefly has created :imported new transaction(s).',
- 'csv_start_over' => 'Import again',
- 'csv_to_index' => 'Back home',
- 'csv_upload_not_writeable' => 'Cannot write to the path mentioned here. Cannot upload',
- 'csv_column__ignore' => '(ignore this column)',
- 'csv_column_account-iban' => 'Asset account (IBAN)',
- 'csv_column_account-id' => 'Asset account ID (matching Firefly)',
- 'csv_column_account-name' => 'Asset account (name)',
- 'csv_column_amount' => 'Amount',
- 'csv_column_amount-comma-separated' => 'Amount (comma as decimal separator)',
- 'csv_column_bill-id' => 'Bill ID (matching Firefly)',
- 'csv_column_bill-name' => 'Bill name',
- 'csv_column_budget-id' => 'Budget ID (matching Firefly)',
- 'csv_column_budget-name' => 'Budget name',
- 'csv_column_category-id' => 'Category ID (matching Firefly)',
- 'csv_column_category-name' => 'Category name',
- 'csv_column_currency-code' => 'Currency code (ISO 4217)',
- 'csv_column_currency-id' => 'Currency ID (matching Firefly)',
- 'csv_column_currency-name' => 'Currency name (matching Firefly)',
- 'csv_column_currency-symbol' => 'Currency symbol (matching Firefly)',
- 'csv_column_date-rent' => 'Rent calculation date',
- 'csv_column_date-transaction' => 'Date',
- 'csv_column_description' => 'Description',
- 'csv_column_opposing-iban' => 'Opposing account (IBAN)',
- 'csv_column_opposing-id' => 'Opposing account ID (matching Firefly)',
- 'csv_column_opposing-name' => 'Opposing account (name)',
- 'csv_column_rabo-debet-credit' => 'Rabobank specific debet/credit indicator',
- 'csv_column_sepa-ct-id' => 'SEPA Credit Transfer end-to-end ID',
- 'csv_column_sepa-ct-op' => 'SEPA Credit Transfer opposing account',
- 'csv_column_sepa-db' => 'SEPA Direct Debet',
- 'csv_column_tags-comma' => 'Tags (comma separated)',
- 'csv_column_tags-space' => 'Tags (space separated)',
- 'csv_specifix_RabobankDescription' => 'Select this when you\'re importing Rabobank CSV export files.',
- 'csv_specifix_AbnAmroDescription' => 'Select this when you\'re importing ABN AMRO CSV export files.',
- 'csv_specifix_Dummy' => 'Checking this has no effect whatsoever.',
- 'csv_import_account_help' => 'If your CSV file does NOT contain information about your asset account(s), use this dropdown to select to which account the transactions in the CSV belong to.',
- 'csv_delimiter_help' => 'Choose the field delimiter that is used in your input file. If not sure, comma is the safest option.',
- 'csv_date_parse_error' => 'Could not parse a valid date from ":value", using the format ":format". Are you sure your CSV is correct?',
+ 'csv_import' => 'Import CSV file',
+ 'csv' => 'CSV',
+ 'csv_index_title' => 'Upload and import a CSV file',
+ 'csv_define_column_roles' => 'Define column roles',
+ 'csv_map_values' => 'Map found values to existing values',
+ 'csv_download_config' => 'Download CSV configuration file.',
+ 'csv_index_text' => 'This form allows you to import a CSV file with transactions into Firefly. It is based on the excellent CSV importer made by the folks at Atlassian. Simply upload your CSV file and follow the instructions. If you would like to learn more, please click on the button at the top of this page.',
+ 'csv_index_beta_warning' => 'This tool is very much in beta. Please proceed with caution',
+ 'csv_header_help' => 'Check this box when your CSV file\'s first row consists of column names, not actual data',
+ 'csv_date_help' => 'Date time format in your CSV. Follow the format like this page indicates. The default value will parse dates that look like this: :dateExample.',
+ 'csv_csv_file_help' => 'Select the CSV file here. You can only upload one file at a time',
+ 'csv_csv_config_file_help' => 'Select your CSV import configuration here. If you do not know what this is, ignore it. It will be explained later.',
+ 'csv_upload_button' => 'Start importing CSV',
+ 'csv_column_roles_title' => 'Define column roles',
+ 'csv_column_roles_text' => 'Firefly does not know what each column means. You need to indicate what every column is. Please check out the example data if you\'re not sure yourself. Click on the question mark (top right of the page) to learn what each column means. If you want to map imported data onto existing data in Firefly, use the checkbox. The next step will show you what this button does.',
+ 'csv_column_roles_table' => 'Column roles',
+ 'csv_column' => 'CSV column',
+ 'csv_column_name' => 'CSV column name',
+ 'csv_column_example' => 'Column example data',
+ 'csv_column_role' => 'Column contains?',
+ 'csv_do_map_value' => 'Map value?',
+ 'csv_continue' => 'Continue to the next step',
+ 'csv_go_back' => 'Go back to the previous step',
+ 'csv_map_title' => 'Map found values to existing values',
+ 'csv_map_text' => 'This page allows you to map the values from the CSV file to existing entries in your database. This ensures that accounts and other things won\'t be created twice.',
+ 'csv_field_value' => 'Field value from CSV',
+ 'csv_field_mapped_to' => 'Must be mapped to...',
+ 'csv_do_not_map' => 'Do not map this value',
+ 'csv_download_config_title' => 'Download CSV configuration',
+ 'csv_download_config_text' => 'Everything you\'ve just set up can be downloaded as a configuration file. Click the button to do so.',
+ 'csv_more_information_text' => 'If the import fails, you can use this configuration file so you don\'t have to start all over again. But, if the import succeeds, it will be easier to upload similar CSV files.',
+ 'csv_do_download_config' => 'Download configuration file.',
+ 'csv_empty_description' => '(empty description)',
+ 'csv_upload_form' => 'CSV upload form',
+ 'csv_index_unsupported_warning' => 'The CSV importer is yet incapable of doing the following:',
+ 'csv_unsupported_map' => 'The importer cannot map the column ":columnRole" to existing values in the database.',
+ 'csv_unsupported_value' => 'The importer does not know how to handle values in columns marked as ":columnRole".',
+ 'csv_cannot_store_value' => 'The importer has not reserved space for columns marked ":columnRole" and will be incapable of processing them.',
+ 'csv_process_title' => 'CSV import finished!',
+ 'csv_process_text' => 'The CSV importer has finished and has processed :rows rows',
+ 'csv_row' => 'Row',
+ 'csv_import_with_errors' => 'There was one error.|There were :errors errors.',
+ 'csv_error_see_logs' => 'Check the log files to see details.',
+ 'csv_process_new_entries' => 'Firefly has created :imported new transaction(s).',
+ 'csv_start_over' => 'Import again',
+ 'csv_to_index' => 'Back home',
+ 'csv_upload_not_writeable' => 'Cannot write to the path mentioned here. Cannot upload',
+ 'csv_column__ignore' => '(ignore this column)',
+ 'csv_column_account-iban' => 'Asset account (IBAN)',
+ 'csv_column_account-id' => 'Asset account ID (matching Firefly)',
+ 'csv_column_account-name' => 'Asset account (name)',
+ 'csv_column_amount' => 'Amount',
+ 'csv_column_amount-comma-separated' => 'Amount (comma as decimal separator)',
+ 'csv_column_bill-id' => 'Bill ID (matching Firefly)',
+ 'csv_column_bill-name' => 'Bill name',
+ 'csv_column_budget-id' => 'Budget ID (matching Firefly)',
+ 'csv_column_budget-name' => 'Budget name',
+ 'csv_column_category-id' => 'Category ID (matching Firefly)',
+ 'csv_column_category-name' => 'Category name',
+ 'csv_column_currency-code' => 'Currency code (ISO 4217)',
+ 'csv_column_currency-id' => 'Currency ID (matching Firefly)',
+ 'csv_column_currency-name' => 'Currency name (matching Firefly)',
+ 'csv_column_currency-symbol' => 'Currency symbol (matching Firefly)',
+ 'csv_column_date-rent' => 'Rent calculation date',
+ 'csv_column_date-transaction' => 'Date',
+ 'csv_column_description' => 'Description',
+ 'csv_column_opposing-iban' => 'Opposing account (IBAN)',
+ 'csv_column_opposing-id' => 'Opposing account ID (matching Firefly)',
+ 'csv_column_opposing-name' => 'Opposing account (name)',
+ 'csv_column_rabo-debet-credit' => 'Rabobank specific debet/credit indicator',
+ 'csv_column_ing-debet-credit' => 'ING specific debet/credit indicator',
+ 'csv_column_sepa-ct-id' => 'SEPA Credit Transfer end-to-end ID',
+ 'csv_column_sepa-ct-op' => 'SEPA Credit Transfer opposing account',
+ 'csv_column_sepa-db' => 'SEPA Direct Debet',
+ 'csv_column_tags-comma' => 'Tags (comma separated)',
+ 'csv_column_tags-space' => 'Tags (space separated)',
+ 'csv_column_account-number' => 'Asset account (account number)',
+ 'csv_column_opposing-number' => 'Opposing account (account number)',
+ 'csv_specifix_RabobankDescription' => 'Select this when you\'re importing Rabobank CSV export files.',
+ 'csv_specifix_AbnAmroDescription' => 'Select this when you\'re importing ABN AMRO CSV export files.',
+ 'csv_specifix_Dummy' => 'Checking this has no effect whatsoever.',
+ 'csv_import_account_help' => 'If your CSV file does NOT contain information about your asset account(s), use this dropdown to select to which account the transactions in the CSV belong to.',
+ 'csv_delimiter_help' => 'Choose the field delimiter that is used in your input file. If not sure, comma is the safest option.',
+ 'csv_date_parse_error' => 'Could not parse a valid date from ":value", using the format ":format". Are you sure your CSV is correct?',
// create new stuff:
- 'create_new_withdrawal' => 'Creer un nouveau retrait',
- 'create_new_deposit' => 'Create new deposit',
- 'create_new_transfer' => 'Creer un nouveau transfert',
- 'create_new_asset' => 'Create new asset account',
- 'create_new_expense' => 'Create new expense account',
- 'create_new_revenue' => 'Create new revenue account',
- 'create_new_piggy_bank' => 'Create new piggy bank',
- 'create_new_bill' => 'Create new bill',
+ 'create_new_withdrawal' => 'Creer un nouveau retrait',
+ 'create_new_deposit' => 'Create new deposit',
+ 'create_new_transfer' => 'Creer un nouveau transfert',
+ 'create_new_asset' => 'Create new asset account',
+ 'create_new_expense' => 'Create new expense account',
+ 'create_new_revenue' => 'Create new revenue account',
+ 'create_new_piggy_bank' => 'Create new piggy bank',
+ 'create_new_bill' => 'Create new bill',
// currencies:
- 'create_currency' => 'Create a new currency',
- 'edit_currency' => 'Edit currency ":name"',
- 'store_currency' => 'Store new currency',
- 'update_currency' => 'Update currency',
- 'new_default_currency' => ':name is now the default currency.',
- 'cannot_delete_currency' => 'Cannot delete :name because there are still transactions attached to it!',
- 'deleted_currency' => 'Currency :name deleted',
- 'created_currency' => 'Currency :name created',
- 'updated_currency' => 'Currency :name updated',
- 'ask_site_owner' => 'Please ask :owner to add, remove or edit currencies.',
- 'currencies_intro' => 'Firefly III supports various currencies which you can set and enable here.',
- 'make_default_currency' => 'make default',
- 'default_currency' => 'default',
+ 'create_currency' => 'Create a new currency',
+ 'edit_currency' => 'Edit currency ":name"',
+ 'store_currency' => 'Store new currency',
+ 'update_currency' => 'Update currency',
+ 'new_default_currency' => ':name is now the default currency.',
+ 'cannot_delete_currency' => 'Cannot delete :name because there are still transactions attached to it!',
+ 'deleted_currency' => 'Currency :name deleted',
+ 'created_currency' => 'Currency :name created',
+ 'updated_currency' => 'Currency :name updated',
+ 'ask_site_owner' => 'Please ask :owner to add, remove or edit currencies.',
+ 'currencies_intro' => 'Firefly III supports various currencies which you can set and enable here.',
+ 'make_default_currency' => 'make default',
+ 'default_currency' => 'default',
// new user:
- 'submit' => 'Submit',
- 'getting_started' => 'Getting started',
- 'to_get_started' => 'To get started with Firefly, please enter your current bank\'s name, and the balance of your checking account:',
- 'savings_balance_text' => 'If you have a savings account, please enter the current balance of your savings account:',
- 'cc_balance_text' => 'If you have a credit card, please enter your credit card\'s limit.',
+ 'submit' => 'Submit',
+ 'getting_started' => 'Getting started',
+ 'to_get_started' => 'To get started with Firefly, please enter your current bank\'s name, and the balance of your checking account:',
+ 'savings_balance_text' => 'If you have a savings account, please enter the current balance of your savings account:',
+ 'cc_balance_text' => 'If you have a credit card, please enter your credit card\'s limit.',
// forms:
- 'mandatoryFields' => 'Mandatory fields',
- 'optionalFields' => 'Optional fields',
- 'options' => 'Options',
- 'something' => 'Something!',
+ 'mandatoryFields' => 'Mandatory fields',
+ 'optionalFields' => 'Optional fields',
+ 'options' => 'Options',
+ 'something' => 'Something!',
// budgets:
- 'create_new_budget' => 'Create a new budget',
- 'store_new_budget' => ' Store new budget',
- 'availableIn' => 'Available in :date',
- 'transactionsWithoutBudget' => 'Expenses without budget',
- 'transactionsWithoutBudgetDate' => 'Expenses without budget in :date',
- 'createBudget' => 'New budget',
- 'inactiveBudgets' => 'Inactive budgets',
- 'without_budget_between' => 'Transactions without a budget between :start and :end',
- 'budget_in_month' => ':name in :month',
- 'delete_budget' => 'Delete budget ":name"',
- 'edit_budget' => 'Edit budget ":name"',
- 'update_amount' => 'Update amount',
- 'update_budget' => 'Update budget',
+ 'create_new_budget' => 'Create a new budget',
+ 'store_new_budget' => ' Store new budget',
+ 'availableIn' => 'Available in :date',
+ 'transactionsWithoutBudget' => 'Expenses without budget',
+ 'transactionsWithoutBudgetDate' => 'Expenses without budget in :date',
+ 'createBudget' => 'New budget',
+ 'inactiveBudgets' => 'Inactive budgets',
+ 'without_budget_between' => 'Transactions without a budget between :start and :end',
+ 'budget_in_month' => ':name in :month',
+ 'delete_budget' => 'Delete budget ":name"',
+ 'edit_budget' => 'Edit budget ":name"',
+ 'update_amount' => 'Update amount',
+ 'update_budget' => 'Update budget',
// bills:
- 'delete_bill' => 'Delete bill ":name"',
- 'edit_bill' => 'Edit bill ":name"',
- 'update_bill' => 'Update bill',
- 'store_new_bill' => 'Store new bill',
+ 'delete_bill' => 'Delete bill ":name"',
+ 'edit_bill' => 'Edit bill ":name"',
+ 'update_bill' => 'Update bill',
+ 'store_new_bill' => 'Store new bill',
// accounts:
- 'details_for_asset' => 'Details for asset account ":name"',
- 'details_for_expense' => 'Details for expense account ":name"',
- 'details_for_revenue' => 'Details for revenue account ":name"',
- 'details_for_cash' => 'Details for cash account ":name"',
- 'store_new_asset_account' => 'Store new asset account',
- 'store_new_expense_account' => 'Store new expense account',
- 'store_new_revenue_account' => 'Store new revenue account',
- 'edit_asset_account' => 'Edit asset account ":name"',
- 'edit_expense_account' => 'Edit expense account ":name"',
- 'edit_revenue_account' => 'Edit revenue account ":name"',
- 'delete_asset_account' => 'Delete asset account ":name"',
- 'delete_expense_account' => 'Delete expense account ":name"',
- 'delete_revenue_account' => 'Delete revenue account ":name"',
- 'asset_deleted' => 'Successfully deleted asset account ":name"',
- 'expense_deleted' => 'Successfully deleted expense account ":name"',
- 'revenue_deleted' => 'Successfully deleted revenue account ":name"',
- 'update_asset_account' => 'Update asset account',
- 'update_expense_account' => 'Update expense account',
- 'update_revenue_account' => 'Update revenue account',
- 'make_new_asset_account' => 'Create a new asset account',
- 'make_new_expense_account' => 'Create a new expense account',
- 'make_new_revenue_account' => 'Create a new revenue account',
- 'asset_accounts' => 'Asset accounts',
- 'expense_accounts' => 'Expense accounts',
- 'revenue_accounts' => 'Revenue accounts',
- 'accountExtraHelp_asset' => '',
- 'accountExtraHelp_expense' => '',
- 'accountExtraHelp_revenue' => '',
- 'account_type' => 'Account type',
- 'save_transactions_by_moving' => 'Save these transaction(s) by moving them to another account:',
+ 'details_for_asset' => 'Details for asset account ":name"',
+ 'details_for_expense' => 'Details for expense account ":name"',
+ 'details_for_revenue' => 'Details for revenue account ":name"',
+ 'details_for_cash' => 'Details for cash account ":name"',
+ 'store_new_asset_account' => 'Store new asset account',
+ 'store_new_expense_account' => 'Store new expense account',
+ 'store_new_revenue_account' => 'Store new revenue account',
+ 'edit_asset_account' => 'Edit asset account ":name"',
+ 'edit_expense_account' => 'Edit expense account ":name"',
+ 'edit_revenue_account' => 'Edit revenue account ":name"',
+ 'delete_asset_account' => 'Delete asset account ":name"',
+ 'delete_expense_account' => 'Delete expense account ":name"',
+ 'delete_revenue_account' => 'Delete revenue account ":name"',
+ 'asset_deleted' => 'Successfully deleted asset account ":name"',
+ 'expense_deleted' => 'Successfully deleted expense account ":name"',
+ 'revenue_deleted' => 'Successfully deleted revenue account ":name"',
+ 'update_asset_account' => 'Update asset account',
+ 'update_expense_account' => 'Update expense account',
+ 'update_revenue_account' => 'Update revenue account',
+ 'make_new_asset_account' => 'Create a new asset account',
+ 'make_new_expense_account' => 'Create a new expense account',
+ 'make_new_revenue_account' => 'Create a new revenue account',
+ 'asset_accounts' => 'Asset accounts',
+ 'expense_accounts' => 'Expense accounts',
+ 'revenue_accounts' => 'Revenue accounts',
+ 'accountExtraHelp_asset' => '',
+ 'accountExtraHelp_expense' => '',
+ 'accountExtraHelp_revenue' => '',
+ 'account_type' => 'Account type',
+ 'save_transactions_by_moving' => 'Save these transaction(s) by moving them to another account:',
// categories:
- 'new_category' => 'New category',
- 'create_new_category' => 'Create a new category',
- 'without_category' => 'Without a category',
- 'update_category' => 'Wijzig categorie',
- 'categories' => 'Categories',
- 'edit_category' => 'Edit category ":name"',
- 'no_category' => '(no category)',
- 'category' => 'Category',
- 'delete_category' => 'Delete category ":name"',
- 'store_category' => 'Store new category',
- 'without_category_between' => 'Without category between :start and :end',
+ 'new_category' => 'New category',
+ 'create_new_category' => 'Create a new category',
+ 'without_category' => 'Without a category',
+ 'update_category' => 'Wijzig categorie',
+ 'categories' => 'Categories',
+ 'edit_category' => 'Edit category ":name"',
+ 'no_category' => '(no category)',
+ 'category' => 'Category',
+ 'delete_category' => 'Delete category ":name"',
+ 'store_category' => 'Store new category',
+ 'without_category_between' => 'Without category between :start and :end',
// transactions:
- 'update_withdrawal' => 'Update withdrawal',
- 'update_deposit' => 'Update deposit',
- 'update_transfer' => 'Update transfer',
- 'delete_withdrawal' => 'Delete withdrawal ":description"',
- 'delete_deposit' => 'Delete deposit ":description"',
- 'delete_transfer' => 'Delete transfer ":description"',
+ 'update_withdrawal' => 'Update withdrawal',
+ 'update_deposit' => 'Update deposit',
+ 'update_transfer' => 'Update transfer',
+ 'delete_withdrawal' => 'Delete withdrawal ":description"',
+ 'delete_deposit' => 'Delete deposit ":description"',
+ 'delete_transfer' => 'Delete transfer ":description"',
// new user:
- 'welcome' => 'Welcome to Firefly!',
- 'createNewAsset' => 'Create a new asset account to get started. ' .
- 'This will allow you to create transactions and start your financial management',
- 'createNewAssetButton' => 'Create new asset account',
+ 'welcome' => 'Welcome to Firefly!',
+ 'createNewAsset' => 'Create a new asset account to get started. ' .
+ 'This will allow you to create transactions and start your financial management',
+ 'createNewAssetButton' => 'Create new asset account',
// home page:
- 'yourAccounts' => 'Your accounts',
- 'budgetsAndSpending' => 'Budgets and spending',
- 'savings' => 'Savings',
- 'markAsSavingsToContinue' => 'Mark your asset accounts as "Savings account" to fill this panel',
- 'createPiggyToContinue' => 'Create piggy banks to fill this panel.',
- 'newWithdrawal' => 'New expense',
- 'newDeposit' => 'New deposit',
- 'newTransfer' => 'New transfer',
- 'moneyIn' => 'Money in',
- 'moneyOut' => 'Money out',
- 'billsToPay' => 'Bills to pay',
- 'billsPaid' => 'Bills paid',
- 'viewDetails' => 'View details',
- 'divided' => 'divided',
- 'toDivide' => 'left to divide',
+ 'yourAccounts' => 'Your accounts',
+ 'budgetsAndSpending' => 'Budgets and spending',
+ 'savings' => 'Savings',
+ 'markAsSavingsToContinue' => 'Mark your asset accounts as "Savings account" to fill this panel',
+ 'createPiggyToContinue' => 'Create piggy banks to fill this panel.',
+ 'newWithdrawal' => 'New expense',
+ 'newDeposit' => 'New deposit',
+ 'newTransfer' => 'New transfer',
+ 'moneyIn' => 'Money in',
+ 'moneyOut' => 'Money out',
+ 'billsToPay' => 'Bills to pay',
+ 'billsPaid' => 'Bills paid',
+ 'viewDetails' => 'View details',
+ 'divided' => 'divided',
+ 'toDivide' => 'left to divide',
// menu and titles, should be recycled as often as possible:
- 'toggleNavigation' => 'Toggle navigation',
- 'currency' => 'Currency',
- 'preferences' => 'Preferences',
- 'logout' => 'Logout',
- 'searchPlaceholder' => 'Search...',
- 'dashboard' => 'Dashboard',
- 'currencies' => 'Currencies',
- 'accounts' => 'Accounts',
- 'Asset account' => 'Asset account',
- 'Default account' => 'Asset account',
- 'Expense account' => 'Expense account',
- 'Revenue account' => 'Revenue account',
- 'Initial balance account' => 'Initial balance account',
- 'budgets' => 'Budgets',
- 'tags' => 'Tags',
- 'reports' => 'Reports',
- 'transactions' => 'Transactions',
- 'expenses' => 'Expenses',
- 'income' => 'Revenue / income',
- 'transfers' => 'Transferts',
- 'moneyManagement' => 'Money management',
- 'piggyBanks' => 'Piggy banks',
- 'bills' => 'Bills',
- 'createNew' => 'Create new',
- 'withdrawal' => 'Withdrawal',
- 'deposit' => 'Deposit',
- 'account' => 'Account',
- 'transfer' => 'Transfer',
- 'Withdrawal' => 'Withdrawal',
- 'Deposit' => 'Deposit',
- 'Transfer' => 'Transfer',
- 'bill' => 'Bill',
- 'yes' => 'Yes',
- 'no' => 'No',
- 'amount' => 'Amount',
- 'newBalance' => 'New balance',
- 'overview' => 'Overview',
- 'saveOnAccount' => 'Save on account',
- 'unknown' => 'Unknown',
- 'daily' => 'Daily',
- 'weekly' => 'Weekly',
- 'monthly' => 'Monthly',
- 'quarterly' => 'Quarterly',
- 'half-year' => 'Every six months',
- 'yearly' => 'Yearly',
- 'profile' => 'Profile',
+ 'toggleNavigation' => 'Toggle navigation',
+ 'currency' => 'Currency',
+ 'preferences' => 'Preferences',
+ 'logout' => 'Logout',
+ 'searchPlaceholder' => 'Search...',
+ 'dashboard' => 'Dashboard',
+ 'currencies' => 'Currencies',
+ 'accounts' => 'Accounts',
+ 'Asset account' => 'Asset account',
+ 'Default account' => 'Asset account',
+ 'Expense account' => 'Expense account',
+ 'Revenue account' => 'Revenue account',
+ 'Initial balance account' => 'Initial balance account',
+ 'budgets' => 'Budgets',
+ 'tags' => 'Tags',
+ 'reports' => 'Reports',
+ 'transactions' => 'Transactions',
+ 'expenses' => 'Expenses',
+ 'income' => 'Revenue / income',
+ 'transfers' => 'Transferts',
+ 'moneyManagement' => 'Money management',
+ 'piggyBanks' => 'Piggy banks',
+ 'bills' => 'Bills',
+ 'createNew' => 'Create new',
+ 'withdrawal' => 'Withdrawal',
+ 'deposit' => 'Deposit',
+ 'account' => 'Account',
+ 'transfer' => 'Transfer',
+ 'Withdrawal' => 'Withdrawal',
+ 'Deposit' => 'Deposit',
+ 'Transfer' => 'Transfer',
+ 'bill' => 'Bill',
+ 'yes' => 'Yes',
+ 'no' => 'No',
+ 'amount' => 'Amount',
+ 'newBalance' => 'New balance',
+ 'overview' => 'Overview',
+ 'saveOnAccount' => 'Save on account',
+ 'unknown' => 'Unknown',
+ 'daily' => 'Daily',
+ 'weekly' => 'Weekly',
+ 'monthly' => 'Monthly',
+ 'quarterly' => 'Quarterly',
+ 'half-year' => 'Every six months',
+ 'yearly' => 'Yearly',
+ 'profile' => 'Profile',
// reports:
- 'report_default' => 'Default financial report for :start until :end',
- 'quick_link_reports' => 'Quick links',
- 'quick_link_default_report' => 'Default financial report',
- 'report_this_month_quick' => 'Current month, all accounts',
- 'report_this_year_quick' => 'Current year, all accounts',
- 'report_this_fiscal_year_quick' => 'Current fiscal year, all accounts',
- 'report_all_time_quick' => 'All-time, all accounts',
- 'reports_can_bookmark' => 'Remember that reports can be bookmarked.',
- 'incomeVsExpenses' => 'Income vs. expenses',
- 'accountBalances' => 'Account balances',
- 'balanceStartOfYear' => 'Balance at start of year',
- 'balanceEndOfYear' => 'Balance at end of year',
- 'balanceStartOfMonth' => 'Balance at start of month',
- 'balanceEndOfMonth' => 'Balance at end of month',
- 'balanceStart' => 'Balance at start of period',
- 'balanceEnd' => 'Balance at end of period',
- 'reportsOwnAccounts' => 'Reports for your own accounts',
- 'reportsOwnAccountsAndShared' => 'Reports for your own accounts and shared accounts',
- 'splitByAccount' => 'Split by account',
- 'balancedByTransfersAndTags' => 'Balanced by transfers and tags',
- 'coveredWithTags' => 'Covered with tags',
- 'leftUnbalanced' => 'Left unbalanced',
- 'expectedBalance' => 'Expected balance',
- 'outsideOfBudgets' => 'Outside of budgets',
- 'leftInBudget' => 'Left in budget',
- 'sumOfSums' => 'Sum of sums',
- 'noCategory' => '(no category)',
- 'notCharged' => 'Not charged (yet)',
- 'inactive' => 'Inactive',
- 'difference' => 'Difference',
- 'in' => 'In',
- 'out' => 'Out',
- 'topX' => 'top :number',
- 'showTheRest' => 'Show everything',
- 'hideTheRest' => 'Show only the top :number',
- 'sum_of_year' => 'Sum of year',
- 'sum_of_years' => 'Sum of years',
- 'average_of_year' => 'Average of year',
- 'average_of_years' => 'Average of years',
- 'categories_earned_in_year' => 'Categories (by earnings)',
- 'categories_spent_in_year' => 'Categories (by spendings)',
- 'report_type' => 'Report type',
- 'report_type_default' => 'Default financial report',
- 'report_included_accounts' => 'Included accounts',
- 'report_date_range' => 'Date range',
- 'report_include_help' => 'In all cases, transfers to shared accounts count as expenses, and transfers from shared accounts count as income.',
- 'report_preset_ranges' => 'Pre-set ranges',
- 'shared' => 'Shared',
- 'fiscal_year' => 'Fiscal year',
+ 'report_default' => 'Default financial report for :start until :end',
+ 'report_audit' => 'Transaction history overview for :start until :end',
+ 'quick_link_reports' => 'Quick links',
+ 'quick_link_default_report' => 'Default financial report',
+ 'report_this_month_quick' => 'Current month, all accounts',
+ 'report_this_year_quick' => 'Current year, all accounts',
+ 'report_this_fiscal_year_quick' => 'Current fiscal year, all accounts',
+ 'report_all_time_quick' => 'All-time, all accounts',
+ 'reports_can_bookmark' => 'Remember that reports can be bookmarked.',
+ 'incomeVsExpenses' => 'Income vs. expenses',
+ 'accountBalances' => 'Account balances',
+ 'balanceStartOfYear' => 'Balance at start of year',
+ 'balanceEndOfYear' => 'Balance at end of year',
+ 'balanceStartOfMonth' => 'Balance at start of month',
+ 'balanceEndOfMonth' => 'Balance at end of month',
+ 'balanceStart' => 'Balance at start of period',
+ 'balanceEnd' => 'Balance at end of period',
+ 'reportsOwnAccounts' => 'Reports for your own accounts',
+ 'reportsOwnAccountsAndShared' => 'Reports for your own accounts and shared accounts',
+ 'splitByAccount' => 'Split by account',
+ 'balancedByTransfersAndTags' => 'Balanced by transfers and tags',
+ 'coveredWithTags' => 'Covered with tags',
+ 'leftUnbalanced' => 'Left unbalanced',
+ 'expectedBalance' => 'Expected balance',
+ 'outsideOfBudgets' => 'Outside of budgets',
+ 'leftInBudget' => 'Left in budget',
+ 'sumOfSums' => 'Sum of sums',
+ 'noCategory' => '(no category)',
+ 'notCharged' => 'Not charged (yet)',
+ 'inactive' => 'Inactive',
+ 'difference' => 'Difference',
+ 'in' => 'In',
+ 'out' => 'Out',
+ 'topX' => 'top :number',
+ 'showTheRest' => 'Show everything',
+ 'hideTheRest' => 'Show only the top :number',
+ 'sum_of_year' => 'Sum of year',
+ 'sum_of_years' => 'Sum of years',
+ 'average_of_year' => 'Average of year',
+ 'average_of_years' => 'Average of years',
+ 'categories_earned_in_year' => 'Categories (by earnings)',
+ 'categories_spent_in_year' => 'Categories (by spendings)',
+ 'report_type' => 'Report type',
+ 'report_type_default' => 'Default financial report',
+ 'report_type_audit' => 'Transaction history overview (audit)',
+ 'report_included_accounts' => 'Included accounts',
+ 'report_date_range' => 'Date range',
+ 'report_include_help' => 'In all cases, transfers to shared accounts count as expenses, and transfers from shared accounts count as income.',
+ 'report_preset_ranges' => 'Pre-set ranges',
+ 'shared' => 'Shared',
+ 'fiscal_year' => 'Fiscal year',
// charts:
- 'dayOfMonth' => 'Day of the month',
- 'month' => 'Month',
- 'budget' => 'Budget',
- 'spent' => 'Spent',
- 'earned' => 'Earned',
- 'overspent' => 'Overspent',
- 'left' => 'Left',
- 'noBudget' => '(no budget)',
- 'maxAmount' => 'Maximum amount',
- 'minAmount' => 'Minumum amount',
- 'billEntry' => 'Current bill entry',
- 'name' => 'Name',
- 'date' => 'Date',
- 'paid' => 'Paid',
- 'unpaid' => 'Unpaid',
- 'day' => 'Day',
- 'budgeted' => 'Budgeted',
- 'period' => 'Period',
- 'balance' => 'Balance',
- 'summary' => 'Summary',
- 'sum' => 'Sum',
- 'average' => 'Average',
- 'balanceFor' => 'Balance for :name',
+ 'dayOfMonth' => 'Day of the month',
+ 'month' => 'Month',
+ 'budget' => 'Budget',
+ 'spent' => 'Spent',
+ 'earned' => 'Earned',
+ 'overspent' => 'Overspent',
+ 'left' => 'Left',
+ 'noBudget' => '(no budget)',
+ 'maxAmount' => 'Maximum amount',
+ 'minAmount' => 'Minumum amount',
+ 'billEntry' => 'Current bill entry',
+ 'name' => 'Name',
+ 'date' => 'Date',
+ 'paid' => 'Paid',
+ 'unpaid' => 'Unpaid',
+ 'day' => 'Day',
+ 'budgeted' => 'Budgeted',
+ 'period' => 'Period',
+ 'balance' => 'Balance',
+ 'summary' => 'Summary',
+ 'sum' => 'Sum',
+ 'average' => 'Average',
+ 'balanceFor' => 'Balance for :name',
// piggy banks:
- 'piggy_bank' => 'Piggy bank',
- 'new_piggy_bank' => 'Create new piggy bank',
- 'store_piggy_bank' => 'Store new piggy bank',
- 'account_status' => 'Account status',
- 'left_for_piggy_banks' => 'Left for piggy banks',
- 'sum_of_piggy_banks' => 'Sum of piggy banks',
- 'saved_so_far' => 'Saved so far',
- 'left_to_save' => 'Left to save',
- 'add_money_to_piggy_title' => 'Add money to piggy bank ":name"',
- 'remove_money_from_piggy_title' => 'Remove money from piggy bank ":name"',
- 'add' => 'Add',
- 'remove' => 'Remove',
- 'max_amount_add' => 'The maximum amount you can add is',
- 'max_amount_remove' => 'The maximum amount you can remove is',
- 'update_piggy_button' => 'Update piggy bank',
- 'update_piggy_title' => 'Update piggy bank ":name"',
- 'details' => 'Details',
- 'events' => 'Events',
- 'target_amount' => 'Target amount',
- 'start_date' => 'Start date',
- 'target_date' => 'Target date',
- 'no_target_date' => 'No target date',
- 'todo' => 'to do',
- 'table' => 'Table',
- 'piggy_bank_not_exists' => 'Piggy bank no longer exists.',
- 'add_any_amount_to_piggy' => 'Add money to this piggy bank to reach your target of :amount.',
- 'add_set_amount_to_piggy' => 'Add :amount to fill this piggy bank on :date',
- 'delete_piggy_bank' => 'Delete piggy bank ":name"',
+ 'piggy_bank' => 'Piggy bank',
+ 'new_piggy_bank' => 'Create new piggy bank',
+ 'store_piggy_bank' => 'Store new piggy bank',
+ 'account_status' => 'Account status',
+ 'left_for_piggy_banks' => 'Left for piggy banks',
+ 'sum_of_piggy_banks' => 'Sum of piggy banks',
+ 'saved_so_far' => 'Saved so far',
+ 'left_to_save' => 'Left to save',
+ 'add_money_to_piggy_title' => 'Add money to piggy bank ":name"',
+ 'remove_money_from_piggy_title' => 'Remove money from piggy bank ":name"',
+ 'add' => 'Add',
+ 'remove' => 'Remove',
+ 'max_amount_add' => 'The maximum amount you can add is',
+ 'max_amount_remove' => 'The maximum amount you can remove is',
+ 'update_piggy_button' => 'Update piggy bank',
+ 'update_piggy_title' => 'Update piggy bank ":name"',
+ 'details' => 'Details',
+ 'events' => 'Events',
+ 'target_amount' => 'Target amount',
+ 'start_date' => 'Start date',
+ 'target_date' => 'Target date',
+ 'no_target_date' => 'No target date',
+ 'todo' => 'to do',
+ 'table' => 'Table',
+ 'piggy_bank_not_exists' => 'Piggy bank no longer exists.',
+ 'add_any_amount_to_piggy' => 'Add money to this piggy bank to reach your target of :amount.',
+ 'add_set_amount_to_piggy' => 'Add :amount to fill this piggy bank on :date',
+ 'delete_piggy_bank' => 'Delete piggy bank ":name"',
// tags
- 'regular_tag' => 'Just a regular tag.',
- 'balancing_act' => 'The tag takes at most two transactions; an expense and a transfer. They\'ll balance each other out.',
- 'advance_payment' => 'The tag accepts one expense and any number of deposits aimed to repay the original expense.',
- 'delete_tag' => 'Supprimer le tag ":tag"',
- 'new_tag' => 'Make new tag',
- 'edit_tag' => 'Editer le tag ":tag"',
- 'no_year' => 'No year set',
- 'no_month' => 'No month set',
- 'tag_title_nothing' => 'Default tags',
- 'tag_title_balancingAct' => 'Balancing act tags',
- 'tag_title_advancePayment' => 'Advance payment tags',
- 'tags_introduction' => 'Usually tags are singular words, designed to quickly band items together using things like expensive, bill or for-party. In Firefly III, tags can have more properties such as a date, description and location. This allows you to join transactions together in a more meaningful way. For example, you could make a tag called Christmas dinner with friends and add information about the restaurant. Such tags are "singular", you would only use them for a single occasion, perhaps with multiple transactions.',
- 'tags_group' => 'Tags group transactions together, which makes it possible to store reimbursements (in case you front money for others) and other "balancing acts" where expenses are summed up (the payments on your new TV) or where expenses and deposits are cancelling each other out (buying something with saved money). It\'s all up to you. Using tags the old-fashioned way is of course always possible.',
- 'tags_start' => 'Create a tag to get started or enter tags when creating new transactions.',
+ 'regular_tag' => 'Just a regular tag.',
+ 'balancing_act' => 'The tag takes at most two transactions; an expense and a transfer. They\'ll balance each other out.',
+ 'advance_payment' => 'The tag accepts one expense and any number of deposits aimed to repay the original expense.',
+ 'delete_tag' => 'Supprimer le tag ":tag"',
+ 'new_tag' => 'Make new tag',
+ 'edit_tag' => 'Editer le tag ":tag"',
+ 'no_year' => 'No year set',
+ 'no_month' => 'No month set',
+ 'tag_title_nothing' => 'Default tags',
+ 'tag_title_balancingAct' => 'Balancing act tags',
+ 'tag_title_advancePayment' => 'Advance payment tags',
+ 'tags_introduction' => 'Usually tags are singular words, designed to quickly band items together using things like expensive, bill or for-party. In Firefly III, tags can have more properties such as a date, description and location. This allows you to join transactions together in a more meaningful way. For example, you could make a tag called Christmas dinner with friends and add information about the restaurant. Such tags are "singular", you would only use them for a single occasion, perhaps with multiple transactions.',
+ 'tags_group' => 'Tags group transactions together, which makes it possible to store reimbursements (in case you front money for others) and other "balancing acts" where expenses are summed up (the payments on your new TV) or where expenses and deposits are cancelling each other out (buying something with saved money). It\'s all up to you. Using tags the old-fashioned way is of course always possible.',
+ 'tags_start' => 'Create a tag to get started or enter tags when creating new transactions.',
];
diff --git a/resources/lang/fr_FR/form.php b/resources/lang/fr_FR/form.php
old mode 100644
new mode 100755
index a572419aec..91c6f5ae34
--- a/resources/lang/fr_FR/form.php
+++ b/resources/lang/fr_FR/form.php
@@ -1,4 +1,12 @@
'Revenue account',
'amount' => 'Amount',
'date' => 'Date',
+ 'interest_date' => 'Interest date',
+ 'book_date' => 'Book date',
+ 'process_date' => 'Processing date',
'category' => 'Category',
'tags' => 'Tags',
'deletePermanently' => 'Delete permanently',
@@ -47,6 +58,7 @@ return [
'symbol' => 'Symbol',
'code' => 'Code',
'iban' => 'IBAN',
+ 'accountNumber' => 'Account number',
'csv' => 'CSV file',
'has_headers' => 'Headers',
'date_format' => 'Date format',
@@ -70,40 +82,44 @@ return [
'size' => 'Size',
'trigger' => 'Trigger',
'stop_processing' => 'Stop processing',
-
- 'csv_comma' => 'A comma (,)',
- 'csv_semicolon' => 'A semicolon (;)',
- 'csv_tab' => 'A tab (invisible)',
-
-
- 'delete_account' => 'Delete account ":name"',
- 'delete_bill' => 'Supprimer la facture ":name"',
- 'delete_budget' => 'Delete budget ":name"',
- 'delete_category' => 'Delete category ":name"',
- 'delete_currency' => 'Delete currency ":name"',
- 'delete_journal' => 'Delete transaction with description ":description"',
- 'delete_attachment' => 'Delete attachment ":name"',
- 'delete_rule' => 'Delete rule ":title"',
- 'delete_rule_group' => 'Delete rule group ":title"',
-
- 'attachment_areYouSure' => 'Are you sure you want to delete the attachment named ":name"?',
- 'account_areYouSure' => 'Are you sure you want to delete the account named ":name"?',
- 'bill_areYouSure' => 'Are you sure you want to delete the bill named ":name"?',
- 'rule_areYouSure' => 'Are you sure you want to delete the rule titled ":title"?',
- 'ruleGroup_areYouSure' => 'Are you sure you want to delete the rule group titled ":title"?',
- 'budget_areYouSure' => 'Are you sure you want to delete the budget named ":name"?',
- 'category_areYouSure' => 'Are you sure you want to delete the category named ":name"?',
- 'currency_areYouSure' => 'Are you sure you want to delete the currency named ":name"?',
- 'piggyBank_areYouSure' => 'Are you sure you want to delete the piggy bank named ":name"?',
- 'journal_areYouSure' => 'Are you sure you want to delete the transaction described ":description"?',
- 'tag_areYouSure' => 'Are you sure you want to delete the tag ":tag"?',
-
- 'permDeleteWarning' => 'Deleting stuff from Firely is permanent and cannot be undone.',
- 'also_delete_transactions' => 'The only transaction connected to this account will be deleted as well.|All :count transactions connected to this account will be deleted as well.',
- 'also_delete_rules' => 'The only rule connected to this rule group will be deleted as well.|All :count rules connected to this rule group will be deleted as well.',
- 'also_delete_piggyBanks' => 'The only piggy bank connected to this account will be deleted as well.|All :count piggy bank connected to this account will be deleted as well.',
- 'bill_keep_transactions' => 'The only transaction connected to this bill will not be deleted.|All :count transactions connected to this bill will spared deletion.',
- 'budget_keep_transactions' => 'The only transaction connected to this budget will not be deleted.|All :count transactions connected to this budget will spared deletion.',
- 'category_keep_transactions' => 'The only transaction connected to this category will not be deleted.|All :count transactions connected to this category will spared deletion.',
- 'tag_keep_transactions' => 'The only transaction connected to this tag will not be deleted.|All :count transactions connected to this tag will spared deletion.',
+ 'start_date' => 'Start of range',
+ 'end_date' => 'End of range',
+ 'export_start_range' => 'Start of export range',
+ 'export_end_range' => 'End of export range',
+ 'export_format' => 'File format',
+ 'include_attachments' => 'Include uploaded attachments',
+ 'include_config' => 'Include configuration file',
+ 'include_old_uploads' => 'Include imported data',
+ 'accounts' => 'Export transactions from these accounts',
+ 'csv_comma' => 'A comma (,)',
+ 'csv_semicolon' => 'A semicolon (;)',
+ 'csv_tab' => 'A tab (invisible)',
+ 'delete_account' => 'Delete account ":name"',
+ 'delete_bill' => 'Supprimer la facture ":name"',
+ 'delete_budget' => 'Delete budget ":name"',
+ 'delete_category' => 'Delete category ":name"',
+ 'delete_currency' => 'Delete currency ":name"',
+ 'delete_journal' => 'Delete transaction with description ":description"',
+ 'delete_attachment' => 'Delete attachment ":name"',
+ 'delete_rule' => 'Delete rule ":title"',
+ 'delete_rule_group' => 'Delete rule group ":title"',
+ 'attachment_areYouSure' => 'Are you sure you want to delete the attachment named ":name"?',
+ 'account_areYouSure' => 'Are you sure you want to delete the account named ":name"?',
+ 'bill_areYouSure' => 'Are you sure you want to delete the bill named ":name"?',
+ 'rule_areYouSure' => 'Are you sure you want to delete the rule titled ":title"?',
+ 'ruleGroup_areYouSure' => 'Are you sure you want to delete the rule group titled ":title"?',
+ 'budget_areYouSure' => 'Are you sure you want to delete the budget named ":name"?',
+ 'category_areYouSure' => 'Are you sure you want to delete the category named ":name"?',
+ 'currency_areYouSure' => 'Are you sure you want to delete the currency named ":name"?',
+ 'piggyBank_areYouSure' => 'Are you sure you want to delete the piggy bank named ":name"?',
+ 'journal_areYouSure' => 'Are you sure you want to delete the transaction described ":description"?',
+ 'tag_areYouSure' => 'Are you sure you want to delete the tag ":tag"?',
+ 'permDeleteWarning' => 'Deleting stuff from Firely is permanent and cannot be undone.',
+ 'also_delete_transactions' => 'The only transaction connected to this account will be deleted as well.|All :count transactions connected to this account will be deleted as well.',
+ 'also_delete_rules' => 'The only rule connected to this rule group will be deleted as well.|All :count rules connected to this rule group will be deleted as well.',
+ 'also_delete_piggyBanks' => 'The only piggy bank connected to this account will be deleted as well.|All :count piggy bank connected to this account will be deleted as well.',
+ 'bill_keep_transactions' => 'The only transaction connected to this bill will not be deleted.|All :count transactions connected to this bill will spared deletion.',
+ 'budget_keep_transactions' => 'The only transaction connected to this budget will not be deleted.|All :count transactions connected to this budget will spared deletion.',
+ 'category_keep_transactions' => 'The only transaction connected to this category will not be deleted.|All :count transactions connected to this category will spared deletion.',
+ 'tag_keep_transactions' => 'The only transaction connected to this tag will not be deleted.|All :count transactions connected to this tag will spared deletion.',
];
diff --git a/resources/lang/fr_FR/help.php b/resources/lang/fr_FR/help.php
old mode 100644
new mode 100755
index 71f96fa6f2..1f2e858d08
--- a/resources/lang/fr_FR/help.php
+++ b/resources/lang/fr_FR/help.php
@@ -1,4 +1,12 @@
'C\'est assez explicite.',
'main-content-end-title' => 'Fin !',
'main-content-end-text' => 'N\'oubliez pas que chaque page a un petit point d\'interrogation en haut à droite. Cliquez dessus pour obtenir de l\'aide concernant la page actuelle.',
-
-
'index' => 'index',
'home' => 'home',
'accounts-index' => 'accounts.index',
diff --git a/resources/lang/fr_FR/list.php b/resources/lang/fr_FR/list.php
old mode 100644
new mode 100755
index 9d7fa6e86a..51b0ded72c
--- a/resources/lang/fr_FR/list.php
+++ b/resources/lang/fr_FR/list.php
@@ -1,6 +1,11 @@
'Nom',
@@ -19,6 +24,9 @@ return [
'description' => 'Description',
'amount' => 'Amount',
'date' => 'Date',
+ 'interest_date' => 'Interest date',
+ 'book_date' => 'Book date',
+ 'process_date' => 'Processing date',
'from' => 'From',
'to' => 'To',
'budget' => 'Budget',
diff --git a/resources/lang/fr_FR/pagination.php b/resources/lang/fr_FR/pagination.php
old mode 100644
new mode 100755
index e16f862ea6..c86fc8b4e9
--- a/resources/lang/fr_FR/pagination.php
+++ b/resources/lang/fr_FR/pagination.php
@@ -1,19 +1,13 @@
'« Precedent',
'next' => 'Suivant »',
-
];
diff --git a/resources/lang/fr_FR/passwords.php b/resources/lang/fr_FR/passwords.php
old mode 100644
new mode 100755
index 49f2dfe6b1..8690468e9e
--- a/resources/lang/fr_FR/passwords.php
+++ b/resources/lang/fr_FR/passwords.php
@@ -8,22 +8,10 @@
*/
return [
-
- /*
- |--------------------------------------------------------------------------
- |--------------------------------------------------------------------------
- |
- | The following language lines are the default lines which match reasons
- | that are given by the password broker for a password update attempt
- | has failed, such as for an invalid token or invalid new password.
- |
- */
-
- "password" => "Le mot de passe doit contenir au moins 6 caractères et correspondre à la confirmation.",
- "user" => "Aucun utilisateur avec cette addresse email.",
- "token" => "Le jeton de réinitialisation de mot de passe est invalide.",
- "sent" => "Nous avons envoyé votre lien de réinitialisation de mot de passe!",
- "reset" => "Le mot de passe a été réinitialisé!",
+ 'password' => 'Passwords must be at least six characters and match the confirmation.',
+ 'user' => 'We can\'t find a user with that e-mail address.',
+ 'token' => 'This password reset token is invalid.',
+ 'sent' => 'We have e-mailed your password reset link!',
+ 'reset' => 'Your password has been reset!',
'blocked' => 'Nice try though.',
-
];
diff --git a/resources/lang/fr_FR/validation.php b/resources/lang/fr_FR/validation.php
old mode 100644
new mode 100755
index 53c07b4811..1a5b75a783
--- a/resources/lang/fr_FR/validation.php
+++ b/resources/lang/fr_FR/validation.php
@@ -1,69 +1,79 @@
'This value is invalid for the selected trigger.',
- 'rule_action_value' => 'This value is invalid for the selected action.',
- 'invalid_domain' => 'Due to security constraints, you cannot register from this domain.',
- 'file_already_attached' => 'Uploaded file ":name" is already attached to this object.',
- 'file_attached' => 'Succesfully uploaded file ":name".',
- 'file_invalid_mime' => 'File ":name" is of type ":mime" which is not accepted as a new upload.',
- 'file_too_large' => 'File ":name" is too large.',
- "accepted" => "Le champ :attribute doit être accepté.",
- "active_url" => "Le champ :attribute n'est pas une URL valide.",
- "after" => "Le champ :attribute doit être une date postérieure au :date.",
- "alpha" => "Le champ :attribute doit seulement contenir des lettres.",
- "alpha_dash" => "Le champ :attribute doit seulement contenir des lettres, des chiffres et des tirets.",
- "alpha_num" => "Le champ :attribute doit seulement contenir des chiffres et des lettres.",
- "array" => "Le champ :attribute doit être un tableau.",
- "unique_for_user" => "There already is an entry with this :attribute.",
- "before" => "Le champ :attribute doit être une date antérieure au :date.",
- 'unique_object_for_user' => 'This name is already in use',
- 'unique_account_for_user' => 'This account name is already in use',
- "between.numeric" => "La valeur de :attribute doit être comprise entre :min et :max.",
- "between.file" => "Le fichier :attribute doit avoir une taille entre :min et :max kilo-octets.",
- "between.string" => "Le texte :attribute doit avoir entre :min et :max caractères.",
- "between.array" => "Le tableau :attribute doit avoir entre :min et :max éléments.",
- "boolean" => "Le champ :attribute doit être vrai ou faux.",
- "confirmed" => "Le champ de confirmation :attribute ne correspond pas.",
- "date" => "Le champ :attribute n'est pas une date valide.",
- "date_format" => "Le champ :attribute ne correspond pas au format :format.",
- "different" => "Les champs :attribute et :other doivent être différents.",
- "digits" => "Le champ :attribute doit avoir :digits chiffres.",
- "digits_between" => "Le champ :attribute doit avoir entre :min et :max chiffres.",
- "email" => "Le champ :attribute doit être une adresse email valide.",
- "filled" => "Le champ :attribute est obligatoire.",
- "exists" => "Le champ :attribute sélectionné est invalide.",
- "image" => "Le champ :attribute doit être une image.",
- "in" => "Le champ :attribute est invalide.",
- "integer" => "Le champ :attribute doit être un entier.",
- "ip" => "Le champ :attribute doit être une adresse IP valide.",
- 'json' => 'Le champ :attribute doit être un document JSON valide.',
- "max.numeric" => "La valeur de :attribute ne peut être supérieure à :max.",
- "max.file" => "Le fichier :attribute ne peut être plus gros que :max kilo-octets.",
- "max.string" => "Le texte de :attribute ne peut contenir plus de :max caractères.",
- "max.array" => "Le tableau :attribute ne peut avoir plus de :max éléments.",
- "mimes" => "Le champ :attribute doit être un fichier de type : :values.",
- "min.numeric" => "La valeur de :attribute doit être supérieure à :min.",
- "min.file" => "Le fichier :attribute doit être plus gros que :min kilo-octets.",
- "min.string" => "Le texte :attribute doit contenir au moins :min caractères.",
- "min.array" => "Le tableau :attribute doit avoir au moins :min éléments.",
- "not_in" => "Le champ :attribute sélectionné n'est pas valide.",
- "numeric" => "Le champ :attribute doit contenir un nombre.",
- "regex" => "Le format du champ :attribute est invalide.",
- "required" => "Le champ :attribute est obligatoire.",
- "required_if" => "Le champ :attribute est obligatoire quand la valeur de :other est :value.",
- 'required_unless' => 'Le champ :attribute est obligatoire sauf si :other est :values.',
- "required_with" => "Le champ :attribute est obligatoire quand :values est présent.",
- "required_with_all" => "Le champ :attribute est obligatoire quand :values est présent.",
- "required_without" => "Le champ :attribute est obligatoire quand :values n'est pas présent.",
- "required_without_all" => "Le champ :attribute est requis quand aucun de :values n'est présent.",
- "same" => "Les champs :attribute et :other doivent être identiques.",
- "size.numeric" => "La valeur de :attribute doit être :size.",
- "size.file" => "La taille du fichier de :attribute doit être de :size kilo-octets.",
- "size.string" => "Le texte de :attribute doit contenir :size caractères.",
- "size.array" => "Le tableau :attribute doit contenir :size éléments.",
- "unique" => "La valeur du champ :attribute est déjà utilisée.",
- 'string' => 'Le champ :attribute doit être une chaîne de caractères.',
- "url" => "Le format de l'URL de :attribute n'est pas valide.",
- "timezone" => "Le champ :attribute doit être un fuseau horaire valide.",
+ 'iban' => 'This is not a valid IBAN.',
+ 'unique_account_number_for_user' => 'It looks like this account number is already in use.',
+ 'rule_trigger_value' => 'This value is invalid for the selected trigger.',
+ 'rule_action_value' => 'This value is invalid for the selected action.',
+ 'invalid_domain' => 'Due to security constraints, you cannot register from this domain.',
+ 'file_already_attached' => 'Uploaded file ":name" is already attached to this object.',
+ 'file_attached' => 'Succesfully uploaded file ":name".',
+ 'file_invalid_mime' => 'File ":name" is of type ":mime" which is not accepted as a new upload.',
+ 'file_too_large' => 'File ":name" is too large.',
+ 'accepted' => 'Le champ :attribute doit être accepté.',
+ 'active_url' => 'Le champ :attribute n\'est pas une URL valide.',
+ 'after' => 'Le champ :attribute doit être une date postérieure au :date.',
+ 'alpha' => 'Le champ :attribute doit seulement contenir des lettres.',
+ 'alpha_dash' => 'Le champ :attribute doit seulement contenir des lettres, des chiffres et des tirets.',
+ 'alpha_num' => 'Le champ :attribute doit seulement contenir des chiffres et des lettres.',
+ 'array' => 'Le champ :attribute doit être un tableau.',
+ 'unique_for_user' => 'There already is an entry with this :attribute.',
+ 'before' => 'Le champ :attribute doit être une date antérieure au :date.',
+ 'unique_object_for_user' => 'This name is already in use',
+ 'unique_account_for_user' => 'This account name is already in use',
+ 'between.numeric' => 'La valeur de :attribute doit être comprise entre :min et :max.',
+ 'between.file' => 'Le fichier :attribute doit avoir une taille entre :min et :max kilo-octets.',
+ 'between.string' => 'Le texte :attribute doit avoir entre :min et :max caractères.',
+ 'between.array' => 'Le tableau :attribute doit avoir entre :min et :max éléments.',
+ 'boolean' => 'Le champ :attribute doit être vrai ou faux.',
+ 'confirmed' => 'Le champ de confirmation :attribute ne correspond pas.',
+ 'date' => 'Le champ :attribute n\'est pas une date valide.',
+ 'date_format' => 'Le champ :attribute ne correspond pas au format :format.',
+ 'different' => 'Les champs :attribute et :other doivent être différents.',
+ 'digits' => 'Le champ :attribute doit avoir :digits chiffres.',
+ 'digits_between' => 'Le champ :attribute doit avoir entre :min et :max chiffres.',
+ 'email' => 'Le champ :attribute doit être une adresse email valide.',
+ 'filled' => 'Le champ :attribute est obligatoire.',
+ 'exists' => 'Le champ :attribute sélectionné est invalide.',
+ 'image' => 'Le champ :attribute doit être une image.',
+ 'in' => 'Le champ :attribute est invalide.',
+ 'integer' => 'Le champ :attribute doit être un entier.',
+ 'ip' => 'Le champ :attribute doit être une adresse IP valide.',
+ 'json' => 'Le champ :attribute doit être un document JSON valide.',
+ 'max.numeric' => 'La valeur de :attribute ne peut être supérieure à :max.',
+ 'max.file' => 'Le fichier :attribute ne peut être plus gros que :max kilo-octets.',
+ 'max.string' => 'Le texte de :attribute ne peut contenir plus de :max caractères.',
+ 'max.array' => 'Le tableau :attribute ne peut avoir plus de :max éléments.',
+ 'mimes' => 'Le champ :attribute doit être un fichier de type : :values.',
+ 'min.numeric' => 'La valeur de :attribute doit être supérieure à :min.',
+ 'min.file' => 'Le fichier :attribute doit être plus gros que :min kilo-octets.',
+ 'min.string' => 'Le texte :attribute doit contenir au moins :min caractères.',
+ 'min.array' => 'Le tableau :attribute doit avoir au moins :min éléments.',
+ 'not_in' => 'Le champ :attribute sélectionné n\'est pas valide.',
+ 'numeric' => 'Le champ :attribute doit contenir un nombre.',
+ 'regex' => 'Le format du champ :attribute est invalide.',
+ 'required' => 'Le champ :attribute est obligatoire.',
+ 'required_if' => 'Le champ :attribute est obligatoire quand la valeur de :other est :value.',
+ 'required_unless' => 'Le champ :attribute est obligatoire sauf si :other est :values.',
+ 'required_with' => 'Le champ :attribute est obligatoire quand :values est présent.',
+ 'required_with_all' => 'Le champ :attribute est obligatoire quand :values est présent.',
+ 'required_without' => 'Le champ :attribute est obligatoire quand :values n\'est pas présent.',
+ 'required_without_all' => 'Le champ :attribute est requis quand aucun de :values n\'est présent.',
+ 'same' => 'Les champs :attribute et :other doivent être identiques.',
+ 'size.numeric' => 'La valeur de :attribute doit être :size.',
+ 'size.file' => 'La taille du fichier de :attribute doit être de :size kilo-octets.',
+ 'size.string' => 'Le texte de :attribute doit contenir :size caractères.',
+ 'size.array' => 'Le tableau :attribute doit contenir :size éléments.',
+ 'unique' => 'La valeur du champ :attribute est déjà utilisée.',
+ 'string' => 'Le champ :attribute doit être une chaîne de caractères.',
+ 'url' => 'Le format de l\'URL de :attribute n\'est pas valide.',
+ 'timezone' => 'Le champ :attribute doit être un fuseau horaire valide.',
+ '2fa_code' => 'The :attribute field is invalid.',
];
diff --git a/resources/lang/nl_NL/breadcrumbs.php b/resources/lang/nl_NL/breadcrumbs.php
old mode 100644
new mode 100755
index 52e1b97a96..8459bf3fc9
--- a/resources/lang/nl_NL/breadcrumbs.php
+++ b/resources/lang/nl_NL/breadcrumbs.php
@@ -1,60 +1,45 @@
'Home',
-
- // accounts
'cash_accounts' => 'Contant geldrekeningen',
'edit_account' => 'Wijzig rekening ":name"',
-
- // currencies
'edit_currency' => 'Wijzig valuta ":name"',
'delete_currency' => 'Verwijder valuta ":name"',
-
- // piggy banks
'newPiggyBank' => 'Nieuw spaarpotje',
'edit_piggyBank' => 'Wijzig spaarpotje ":name"',
-
- // top menu
'preferences' => 'Voorkeuren',
'profile' => 'Profiel',
'changePassword' => 'Verander je wachtwoord',
-
- // bills
'bills' => 'Contracten',
'newBill' => 'Nieuw contract',
'edit_bill' => 'Wijzig contract ":name"',
'delete_bill' => 'Verwijder contract ":name"',
-
- // reports
'reports' => 'Overzichten',
'monthly_report' => 'Maandoverzicht :date',
'monthly_report_shared' => 'Maandoverzicht :date (inclusief gedeelde rekeningen)',
'yearly_report' => 'Jaaroverzicht :date',
'yearly_report_shared' => 'Jaaroverzicht :date (inclusief gedeelde rekeningen)',
'budget_report' => 'Budgetoverzicht :date',
-
- // search
'searchResult' => 'Zoeken naar ":query"',
-
- // transaction lists.
'withdrawal_list' => 'Uitgaven',
'deposit_list' => 'Inkomsten',
'transfer_list' => 'Overschrijvingen',
'transfers_list' => 'Overschrijvingen',
-
- // create transactions
'create_withdrawal' => 'Sla nieuwe uitgave op',
'create_deposit' => 'Sla nieuwe inkomsten op',
'create_transfer' => 'Sla nieuwe overschrijving op',
-
- // edit transactions
'edit_journal' => 'Wijzig transactie ":description"',
'delete_journal' => 'Verwijder transactie ":description"',
-
- // tags
'tags' => 'Tags',
'createTag' => 'Maak nieuwe tag',
'edit_tag' => 'Wijzig tag ":tag"',
'delete_tag' => 'Verwijder tag ":tag"',
-
];
diff --git a/resources/lang/nl_NL/config.php b/resources/lang/nl_NL/config.php
old mode 100644
new mode 100755
index 55f590c9a3..518974346d
--- a/resources/lang/nl_NL/config.php
+++ b/resources/lang/nl_NL/config.php
@@ -1,8 +1,20 @@
'nl, Dutch, nl_NL, nl_NL.utf8',
- 'month' => '%B %Y',
- 'month_and_day' => '%e %B %Y',
-
+ 'locale' => 'nl, Dutch, nl_NL, nl_NL.utf8',
+ 'month' => '%B %Y',
+ 'month_and_day' => '%e %B %Y',
+ 'date_time' => '%e %B %Y, @ %T',
+ 'specific_day' => '%e %B %Y',
+ 'week_in_year' => 'week %W, %Y',
+ 'quarter_of_year' => '%B %Y',
+ 'year' => '%Y',
+ 'half_year' => '%B %Y',
];
diff --git a/resources/lang/nl_NL/firefly.php b/resources/lang/nl_NL/firefly.php
old mode 100644
new mode 100755
index 5f02d0c10a..d1df014f6b
--- a/resources/lang/nl_NL/firefly.php
+++ b/resources/lang/nl_NL/firefly.php
@@ -1,111 +1,177 @@
'Deze taal is nog niet helemaal af',
- 'test' => 'Nederlands geselecteerd!',
- 'close' => 'Sluiten',
- 'pleaseHold' => 'Momentje...',
- 'actions' => 'Acties',
- 'edit' => 'Wijzig',
- 'delete' => 'Verwijder',
- 'welcomeBack' => 'Hoe staat het er voor?',
- 'everything' => 'Alles',
- 'customRange' => 'Zelf bereik kiezen',
- 'apply' => 'Go',
- 'cancel' => 'Annuleren',
- 'from' => 'Van',
- 'to' => 'Tot',
- 'total_sum' => 'Totale som',
- 'period_sum' => 'Som van periode',
- 'showEverything' => 'Laat alles zien',
- 'never' => 'Nooit',
- 'search_results_for' => 'Zoekresultaten voor ":query"',
- 'bounced_error' => 'Het emailtje naar :email kwam nooit aan.',
- 'deleted_error' => 'Deze gegevens zijn niet correct.',
- 'general_blocked_error' => 'Je account is uitgeschakeld, je kan helaas niet inloggen.',
- 'removed_amount' => ':amount weggehaald',
- 'added_amount' => ':amount toegevoegd',
- 'asset_account_role_help' => 'Voorkeuren die voortkomen uit je keuze hier kan je later aangeven.',
- 'Opening balance' => 'Startsaldo',
- 'create_new_stuff' => 'Nieuw',
- 'new_withdrawal' => 'Nieuwe uitgave',
- 'new_deposit' => 'Nieuwe inkomsten',
- 'new_transfer' => 'Nieuwe overschrijving',
- 'new_asset_account' => 'Nieuwe betaalrekening',
- 'new_expense_account' => 'Nieuwe crediteur',
- 'new_revenue_account' => 'Nieuwe debiteur',
- 'new_budget' => 'Nieuw budget',
- 'new_bill' => 'Nieuw contract',
+ 'language_incomplete' => 'Deze taal is nog niet helemaal af',
+ 'test' => 'Nederlands geselecteerd!',
+ 'close' => 'Sluiten',
+ 'pleaseHold' => 'Momentje...',
+ 'actions' => 'Acties',
+ 'edit' => 'Wijzig',
+ 'delete' => 'Verwijder',
+ 'welcomeBack' => 'Hoe staat het er voor?',
+ 'everything' => 'Alles',
+ 'customRange' => 'Zelf bereik kiezen',
+ 'apply' => 'Go',
+ 'cancel' => 'Annuleren',
+ 'from' => 'Van',
+ 'to' => 'Tot',
+ 'total_sum' => 'Totale som',
+ 'period_sum' => 'Som van periode',
+ 'showEverything' => 'Laat alles zien',
+ 'never' => 'Nooit',
+ 'search_results_for' => 'Zoekresultaten voor ":query"',
+ 'bounced_error' => 'Het emailtje naar :email kwam nooit aan.',
+ 'deleted_error' => 'Deze gegevens zijn niet correct.',
+ 'general_blocked_error' => 'Je account is uitgeschakeld, je kan helaas niet inloggen.',
+ 'removed_amount' => ':amount weggehaald',
+ 'added_amount' => ':amount toegevoegd',
+ 'asset_account_role_help' => 'Voorkeuren die voortkomen uit je keuze hier kan je later aangeven.',
+ 'Opening balance' => 'Startsaldo',
+ 'create_new_stuff' => 'Nieuw',
+ 'new_withdrawal' => 'Nieuwe uitgave',
+ 'new_deposit' => 'Nieuwe inkomsten',
+ 'new_transfer' => 'Nieuwe overschrijving',
+ 'new_asset_account' => 'Nieuwe betaalrekening',
+ 'new_expense_account' => 'Nieuwe crediteur',
+ 'new_revenue_account' => 'Nieuwe debiteur',
+ 'new_budget' => 'Nieuw budget',
+ 'new_bill' => 'Nieuw contract',
+ 'block_account_logout' => 'Je bent helaas uitgelogd. Geblokkeerde accounts kunnen deze site niet gebruiken. Heb je een geldig e-mailadres gebruikt toen je je registreerde?',
+ 'flash_success' => 'Gelukt!',
+ 'flash_info' => 'Melding',
+ 'flash_warning' => 'Waarschuwing!',
+ 'flash_error' => 'Fout!',
+ 'flash_info_multiple' => 'Er is één melding|Er zijn :count meldingen',
+ 'flash_error_multiple' => 'Er is één fout|Er zijn :count fouten',
+ 'net_worth' => 'Kapitaal',
+ 'route_has_no_help' => 'Er is geen helptekst voor deze pagina, of er is geen helptekst in het Nederlands.',
+ 'two_factor_welcome' => 'Hoi :user!',
+ 'two_factor_enter_code' => 'Vul je authenticatiecode in. Je authenticatieapplicatie kan deze voor je genereren.',
+ 'two_factor_code_here' => 'Code',
+ 'authenticate' => 'Inloggen',
+ 'two_factor_forgot' => 'Ik kan geen codes meer genereren.',
+ 'two_factor_lost_header' => 'Kan je geen codes meer genereren?',
+ 'two_factor_lost_intro' => 'Dit is helaas niet iets dat je kan resetten vanaf de site. Je hebt twee keuzes.',
+ 'two_factor_lost_fix_self' => 'Als dit jouw installatie van Firefly III is, vind je in de logboeken (storage/logs
) instructies.',
+ 'two_factor_lost_fix_owner' => 'Zo niet, stuur dan een e-mail naar :site_owner en vraag of ze je authenticatie in twee stappen willen resetten.',
+
+ // export data:
+ 'import_and_export' => 'Import en export',
+ 'export_data' => 'Exporteren',
+ 'export_data_intro' => 'Om te backuppen, of wanneer je naar een ander systeem verhuist.',
+ 'export_format' => 'Exporteerformaat',
+ 'export_format_csv' => 'Komma-gescheiden bestand (CSV)',
+ 'export_format_mt940' => 'MT940 bestand',
+ 'export_included_accounts' => 'Exporteer transacties van deze rekeningen',
+ 'include_config_help' => 'Voor het makkelijk opnieuw importeren in Firefly III',
+ 'include_old_uploads_help' => 'Firefly III gooit je oude geïmporteerde CSV bestanden niet weg. Je kan ze meenemen in je exportbestand.',
+ 'do_export' => 'Exporteren',
+ 'export_status_never_started' => 'Het exporteren is nog niet begonnen',
+ 'export_status_make_exporter' => 'Exporteerding maken...',
+ 'export_status_collecting_journals' => 'Overboekingen verzamelen...',
+ 'export_status_collected_journals' => 'Overboekingen verzameld!',
+ 'export_status_converting_to_export_format' => 'Overboekingen overzetten...',
+ 'export_status_converted_to_export_format' => 'Overboekingen overgezet!',
+ 'export_status_creating_journal_file' => 'Exportbestand maken...',
+ 'export_status_created_journal_file' => 'Exportbestand gemaakt!',
+ 'export_status_collecting_attachments' => 'Bijlagen verzamelen...',
+ 'export_status_collected_attachments' => 'Bijlagen verzameld!',
+ 'export_status_collecting_old_uploads' => 'Oude uploads verzamelen...',
+ 'export_status_collected_old_uploads' => 'Oude uploads verzameld!',
+ 'export_status_creating_config_file' => 'Configuratiebestand maken...',
+ 'export_status_created_config_file' => 'Configuratiebestand gemaakt!',
+ 'export_status_creating_zip_file' => 'Zipbestand maken...',
+ 'export_status_created_zip_file' => 'Zipbestand gemaakt!',
+ 'export_status_finished' => 'Klaar met exportbestand! Hoera!',
+ 'export_data_please_wait' => 'Een ogenblik geduld...',
+ 'attachment_explanation' => 'Het bestand \':attachment_name\' (#:attachment_id) werd oorspronkelijk geüpload naar (Engels) :type \':description\' (#:journal_id), met datum :date en bedrag :amount.',
// rules
- 'rules' => 'Regels',
- 'rules_explanation' => 'Hier kan je regels instellen. Regels worden in werking gesteld als je een bij-, afschrijving of overboeking maakt (of verandert). Als die transactie bepaalde eigenschappen heeft (zogenaamde "triggers") zal Firefly de bijbehorende "acties" uitvoeren. Gecombineerd kan je Firefly op een bepaalde manier laten reageren op nieuwe transacties.',
- 'rule_name' => 'Regelnaam',
- 'rule_triggers' => 'Regel reageert op',
- 'rule_actions' => 'Regel zal dan',
- 'new_rule' => 'Nieuwe regel',
- 'new_rule_group' => 'Nieuwe regelgroep',
- 'rule_priority_up' => 'Geef regel meer prioriteit',
- 'rule_priority_down' => 'Geef regel minder prioriteit',
- 'make_new_rule_group' => 'Maak nieuwe regelgroep',
- 'store_new_rule_group' => 'Sla nieuwe regelgroep op',
- 'created_new_rule_group' => 'Nieuwe regelgroep ":title" opgeslagen!',
- 'updated_rule_group' => 'Regelgroep ":title" geüpdatet.',
- 'edit_rule_group' => 'Wijzig regelgroep ":title"',
- 'delete_rule_group' => 'Verwijder regelgroep ":title"',
- 'deleted_rule_group' => 'Regelgroep ":title" verwijderd',
- 'update_rule_group' => 'Wijzig regelgroep',
- 'no_rules_in_group' => 'Er zijn geen regels in deze groep',
- 'move_rule_group_up' => 'Verplaats regelgroep omhoog',
- 'move_rule_group_down' => 'Verplaats regelgroep omlaag',
- 'save_rules_by_moving' => 'Red deze regel(s) van de ondergang door ze te verplaatsen naar een andere regelgroep:',
- 'make_new_rule' => 'Maak een nieuwe regel in regelgroep ":title"',
- 'rule_help_stop_processing' => 'Zet hier een vinkje om latere regels in deze groep te negeren.',
- 'rule_help_active' => 'Niet actieve regels zullen nooit worden gecontroleerd.',
- 'stored_new_rule' => 'Nieuwe regel ":title" opgeslagen',
- 'deleted_rule' => 'Regel ":title" verwijderd',
- 'store_new_rule' => 'Sla nieuwe regel op',
- 'updated_rule' => 'Regel ":title" geüpdatet',
- 'default_rule_group_name' => 'Standaard regels',
- 'default_rule_group_description' => 'Al je regels die niet in een bepaalde groep zitten.',
- 'default_rule_name' => 'Je eerste standaardregel',
- 'default_rule_description' => 'Deze regel is een voorbeeld. Je kan hem rustig verwijderen.',
- 'default_rule_trigger_description' => 'The Man Who Sold the World',
- 'default_rule_trigger_from_account' => 'David Bowie',
- 'default_rule_action_prepend' => 'Kocht de wereld van ',
- 'default_rule_action_set_category' => 'Grote uitgaven',
-
- 'trigger' => 'Trigger',
- 'trigger_value' => 'Trigger bij waarde',
- 'stop_processing_other_triggers' => 'Reageer niet meer op andere triggers',
- 'add_rule_trigger' => 'Nieuwe trigger toevoegen',
- 'action' => 'Actie',
- 'action_value' => 'Actie-waarde',
- 'stop_executing_other_actions' => 'Voer verdere acties niet uit',
- 'add_rule_action' => 'Nieuwe actie toevoegen',
- 'edit_rule' => 'Wijzig regel ":title"',
- 'update_rule' => 'Werk regel bij',
+ 'rules' => 'Regels',
+ 'rules_explanation' => 'Hier kan je regels instellen. Regels worden in werking gesteld als je een bij-, afschrijving of overboeking maakt (of verandert). Als die transactie bepaalde eigenschappen heeft (zogenaamde "triggers") zal Firefly de bijbehorende "acties" uitvoeren. Gecombineerd kan je Firefly op een bepaalde manier laten reageren op nieuwe transacties.',
+ 'rule_name' => 'Regelnaam',
+ 'rule_triggers' => 'Regel reageert op',
+ 'rule_actions' => 'Regel zal dan',
+ 'new_rule' => 'Nieuwe regel',
+ 'new_rule_group' => 'Nieuwe regelgroep',
+ 'rule_priority_up' => 'Geef regel meer prioriteit',
+ 'rule_priority_down' => 'Geef regel minder prioriteit',
+ 'make_new_rule_group' => 'Maak nieuwe regelgroep',
+ 'store_new_rule_group' => 'Sla nieuwe regelgroep op',
+ 'created_new_rule_group' => 'Nieuwe regelgroep ":title" opgeslagen!',
+ 'updated_rule_group' => 'Regelgroep ":title" geüpdatet.',
+ 'edit_rule_group' => 'Wijzig regelgroep ":title"',
+ 'delete_rule_group' => 'Verwijder regelgroep ":title"',
+ 'deleted_rule_group' => 'Regelgroep ":title" verwijderd',
+ 'update_rule_group' => 'Wijzig regelgroep',
+ 'no_rules_in_group' => 'Er zijn geen regels in deze groep',
+ 'move_rule_group_up' => 'Verplaats regelgroep omhoog',
+ 'move_rule_group_down' => 'Verplaats regelgroep omlaag',
+ 'save_rules_by_moving' => 'Red deze regel(s) van de ondergang door ze te verplaatsen naar een andere regelgroep:',
+ 'make_new_rule' => 'Maak een nieuwe regel in regelgroep ":title"',
+ 'rule_help_stop_processing' => 'Zet hier een vinkje om latere regels in deze groep te negeren.',
+ 'rule_help_active' => 'Niet actieve regels zullen nooit worden gecontroleerd.',
+ 'stored_new_rule' => 'Nieuwe regel ":title" opgeslagen',
+ 'deleted_rule' => 'Regel ":title" verwijderd',
+ 'store_new_rule' => 'Sla nieuwe regel op',
+ 'updated_rule' => 'Regel ":title" geüpdatet',
+ 'default_rule_group_name' => 'Standaard regels',
+ 'default_rule_group_description' => 'Al je regels die niet in een bepaalde groep zitten.',
+ 'default_rule_name' => 'Je eerste standaardregel',
+ 'default_rule_description' => 'Deze regel is een voorbeeld. Je kan hem rustig verwijderen.',
+ 'default_rule_trigger_description' => 'The Man Who Sold the World',
+ 'default_rule_trigger_from_account' => 'David Bowie',
+ 'default_rule_action_prepend' => 'Kocht de wereld van ',
+ 'default_rule_action_set_category' => 'Grote uitgaven',
+ 'trigger' => 'Trigger',
+ 'trigger_value' => 'Trigger bij waarde',
+ 'stop_processing_other_triggers' => 'Reageer niet meer op andere triggers',
+ 'add_rule_trigger' => 'Nieuwe trigger toevoegen',
+ 'action' => 'Actie',
+ 'action_value' => 'Actie-waarde',
+ 'stop_executing_other_actions' => 'Voer verdere acties niet uit',
+ 'add_rule_action' => 'Nieuwe actie toevoegen',
+ 'edit_rule' => 'Wijzig regel ":title"',
+ 'delete_rule' => 'Verwijder regel ":title"',
+ 'update_rule' => 'Werk regel bij',
+ 'test_rule_triggers' => 'Bekijk welke transacties hieraan voldoen',
+ 'warning_transaction_subset' => 'Je ziet hier maximaal :max_num_transactions transacties omdat je anders veel te lang moet wachten',
+ 'warning_no_matching_transactions' => 'Niks gevonden in je laatste :num_transactions transacties.',
+ 'warning_no_valid_triggers' => 'Geen geldige triggers gevonden.',
+ 'execute_on_existing_transactions' => 'Toepassen op bestaande transacties',
+ 'execute_on_existing_transactions_intro' => 'Wanneer een regel of groep is veranderd of toegevoegd, kun je hem hier uitvoeren voor bestaande transacties',
+ 'execute_on_existing_transactions_short' => 'Bestaande transacties',
+ 'executed_group_on_existing_transactions' => 'Regelgroep ":title" is uitgevoerd op bestaande transacties',
+ 'execute_group_on_existing_transactions' => 'Regelgroep uitvoeren op bestaande transacties',
+ 'include_transactions_from_accounts' => 'Gebruik transacties van deze rekeningen',
+ 'execute' => 'Uitvoeren',
// actions and triggers
- 'rule_trigger_user_action' => 'Gebruikersactie is ":trigger_value"',
- 'rule_trigger_from_account_starts' => 'Bronrekeningnaam begint met ":trigger_value"',
- 'rule_trigger_from_account_ends' => 'Bronrekeningnaam eindigt op ":trigger_value"',
- 'rule_trigger_from_account_is' => 'Bronrekeningnaam is ":trigger_value"',
- 'rule_trigger_from_account_contains' => 'Bronrekeningnaam bevat ":trigger_value"',
- 'rule_trigger_to_account_starts' => 'Doelrekeningnaam begint met ":trigger_value"',
- 'rule_trigger_to_account_ends' => 'Doelrekeningnaam eindigt op ":trigger_value"',
- 'rule_trigger_to_account_is' => 'Doelrekeningnaam is ":trigger_value"',
- 'rule_trigger_to_account_contains' => 'Doelrekeningnaam bevat ":trigger_value"',
- 'rule_trigger_transaction_type' => 'Transactiesoort is ":trigger_value" (Engels)',
- 'rule_trigger_amount_less' => 'Bedrag is minder dan :trigger_value',
- 'rule_trigger_amount_exactly' => 'Bedrag is :trigger_value',
- 'rule_trigger_amount_more' => 'Bedrag is meer dan :trigger_value',
- 'rule_trigger_description_starts' => 'Omschrijving begint met ":trigger_value"',
- 'rule_trigger_description_ends' => 'Omschrijving eindigt op ":trigger_value"',
- 'rule_trigger_description_contains' => 'Omschrijving bevat ":trigger_value"',
- 'rule_trigger_description_is' => 'Omschrijving is ":trigger_value"',
-
+ 'rule_trigger_user_action' => 'Gebruikersactie is ":trigger_value"',
+ 'rule_trigger_from_account_starts' => 'Bronrekeningnaam begint met ":trigger_value"',
+ 'rule_trigger_from_account_ends' => 'Bronrekeningnaam eindigt op ":trigger_value"',
+ 'rule_trigger_from_account_is' => 'Bronrekeningnaam is ":trigger_value"',
+ 'rule_trigger_from_account_contains' => 'Bronrekeningnaam bevat ":trigger_value"',
+ 'rule_trigger_to_account_starts' => 'Doelrekeningnaam begint met ":trigger_value"',
+ 'rule_trigger_to_account_ends' => 'Doelrekeningnaam eindigt op ":trigger_value"',
+ 'rule_trigger_to_account_is' => 'Doelrekeningnaam is ":trigger_value"',
+ 'rule_trigger_to_account_contains' => 'Doelrekeningnaam bevat ":trigger_value"',
+ 'rule_trigger_transaction_type' => 'Transactiesoort is ":trigger_value" (Engels)',
+ 'rule_trigger_amount_less' => 'Bedrag is minder dan :trigger_value',
+ 'rule_trigger_amount_exactly' => 'Bedrag is :trigger_value',
+ 'rule_trigger_amount_more' => 'Bedrag is meer dan :trigger_value',
+ 'rule_trigger_description_starts' => 'Omschrijving begint met ":trigger_value"',
+ 'rule_trigger_description_ends' => 'Omschrijving eindigt op ":trigger_value"',
+ 'rule_trigger_description_contains' => 'Omschrijving bevat ":trigger_value"',
+ 'rule_trigger_description_is' => 'Omschrijving is ":trigger_value"',
'rule_trigger_from_account_starts_choice' => 'Bronrekening naam begint met..',
'rule_trigger_from_account_ends_choice' => 'Bronrekening eindigt op..',
'rule_trigger_from_account_is_choice' => 'Bronrekening is..',
@@ -122,486 +188,498 @@ return [
'rule_trigger_description_ends_choice' => 'Omschrijving eindigt op..',
'rule_trigger_description_contains_choice' => 'Omschrijving bevat..',
'rule_trigger_description_is_choice' => 'Omschrijving is..',
-
- 'rule_trigger_store_journal' => 'Als een transactie wordt gemaakt',
- 'rule_trigger_update_journal' => 'Als een transactie wordt bewerkt',
-
- 'rule_action_set_category' => 'Verander categorie naar ":action_value"',
- 'rule_action_clear_category' => 'Maak categorie-veld leeg',
- 'rule_action_set_budget' => 'Sla op onder budget ":action_value"',
- 'rule_action_clear_budget' => 'Sla op zonder budget',
- 'rule_action_add_tag' => 'Voeg tag ":action_value" toe',
- 'rule_action_remove_tag' => 'Haal tag ":action_value" weg',
- 'rule_action_remove_all_tags' => 'Haal alle tags weg',
- 'rule_action_set_description' => 'Geef omschrijving ":action_value"',
- 'rule_action_append_description' => 'Zet ":action_value" voor de omschrijving',
- 'rule_action_prepend_description' => 'Zet ":action_value" voor de omschrijving',
-
- 'rule_action_set_category_choice' => 'Geef categorie..',
- 'rule_action_clear_category_choice' => 'Geef geen categorie',
- 'rule_action_set_budget_choice' => 'Sla op onder budget..',
- 'rule_action_clear_budget_choice' => 'Maak budget-veld leeg',
- 'rule_action_add_tag_choice' => 'Voeg tag toe..',
- 'rule_action_remove_tag_choice' => 'Haal tag weg..',
- 'rule_action_remove_all_tags_choice' => 'Haal alle tags weg',
- 'rule_action_set_description_choice' => 'Geef omschrijving..',
- 'rule_action_append_description_choice' => 'Zet .. achter de omschrijving',
- 'rule_action_prepend_description_choice' => 'Zet .. voor de omschrijving',
+ 'rule_trigger_store_journal' => 'Als een transactie wordt gemaakt',
+ 'rule_trigger_update_journal' => 'Als een transactie wordt bewerkt',
+ 'rule_action_set_category' => 'Verander categorie naar ":action_value"',
+ 'rule_action_clear_category' => 'Maak categorie-veld leeg',
+ 'rule_action_set_budget' => 'Sla op onder budget ":action_value"',
+ 'rule_action_clear_budget' => 'Sla op zonder budget',
+ 'rule_action_add_tag' => 'Voeg tag ":action_value" toe',
+ 'rule_action_remove_tag' => 'Haal tag ":action_value" weg',
+ 'rule_action_remove_all_tags' => 'Haal alle tags weg',
+ 'rule_action_set_description' => 'Geef omschrijving ":action_value"',
+ 'rule_action_append_description' => 'Zet ":action_value" voor de omschrijving',
+ 'rule_action_prepend_description' => 'Zet ":action_value" voor de omschrijving',
+ 'rule_action_set_category_choice' => 'Geef categorie..',
+ 'rule_action_clear_category_choice' => 'Geef geen categorie',
+ 'rule_action_set_budget_choice' => 'Sla op onder budget..',
+ 'rule_action_clear_budget_choice' => 'Maak budget-veld leeg',
+ 'rule_action_add_tag_choice' => 'Voeg tag toe..',
+ 'rule_action_remove_tag_choice' => 'Haal tag weg..',
+ 'rule_action_remove_all_tags_choice' => 'Haal alle tags weg',
+ 'rule_action_set_description_choice' => 'Geef omschrijving..',
+ 'rule_action_append_description_choice' => 'Zet .. achter de omschrijving',
+ 'rule_action_prepend_description_choice' => 'Zet .. voor de omschrijving',
// tags
- 'store_new_tag' => 'Sla tag op',
- 'update_tag' => 'Sla wijzigingen op',
- 'no_location_set' => 'Zonder plaats',
- 'meta_data' => 'Metagegevens',
- 'location' => 'Plaats',
+ 'store_new_tag' => 'Sla tag op',
+ 'update_tag' => 'Sla wijzigingen op',
+ 'no_location_set' => 'Zonder plaats',
+ 'meta_data' => 'Metagegevens',
+ 'location' => 'Plaats',
// preferences
- 'pref_home_screen_accounts' => 'Voorpaginarekeningen',
- 'pref_home_screen_accounts_help' => 'Welke betaalrekeningen wil je op de voorpagina zien?',
- 'pref_budget_settings' => 'Budgetinstellingen',
- 'pref_budget_settings_help' => 'Wat is het maximale bedrag dat je voor een budget kan instellen?',
- 'pref_view_range' => 'Bereik',
- 'pref_view_range_help' => 'Sommige pagina\'s springen naar een standaard bereik. Welk bereik heeft jouw voorkeur?',
- 'pref_1D' => 'Eén dag',
- 'pref_1W' => 'Eén week',
- 'pref_1M' => 'Eén maand',
- 'pref_3M' => 'Drie maanden (kwartaal)',
- 'pref_6M' => 'Zes maanden',
- 'pref_languages' => 'Talen',
- 'pref_languages_help' => 'Firefly III ondersteunt meerdere talen. Welke heeft jouw voorkeur?',
- 'pref_custom_fiscal_year' => 'Instellingen voor boekjaar',
- 'pref_custom_fiscal_year_label' => 'Ingeschakeld',
- 'pref_custom_fiscal_year_help' => 'Voor in landen die een boekjaar gebruiken anders dan 1 januari tot 31 december',
- 'pref_fiscal_year_start_label' => 'Start van boekjaar',
- 'pref_save_settings' => 'Instellingen opslaan',
+ 'pref_home_screen_accounts' => 'Voorpaginarekeningen',
+ 'pref_home_screen_accounts_help' => 'Welke betaalrekeningen wil je op de voorpagina zien?',
+ 'pref_budget_settings' => 'Budgetinstellingen',
+ 'pref_budget_settings_help' => 'Wat is het maximale bedrag dat je voor een budget kan instellen?',
+ 'pref_view_range' => 'Bereik',
+ 'pref_view_range_help' => 'Sommige pagina\'s springen naar een standaard bereik. Welk bereik heeft jouw voorkeur?',
+ 'pref_1D' => 'Eén dag',
+ 'pref_1W' => 'Eén week',
+ 'pref_1M' => 'Eén maand',
+ 'pref_3M' => 'Drie maanden (kwartaal)',
+ 'pref_6M' => 'Zes maanden',
+ 'pref_languages' => 'Talen',
+ 'pref_languages_help' => 'Firefly III ondersteunt meerdere talen. Welke heeft jouw voorkeur?',
+ 'pref_custom_fiscal_year' => 'Instellingen voor boekjaar',
+ 'pref_custom_fiscal_year_label' => 'Ingeschakeld',
+ 'pref_custom_fiscal_year_help' => 'Voor in landen die een boekjaar gebruiken anders dan 1 januari tot 31 december',
+ 'pref_fiscal_year_start_label' => 'Start van boekjaar',
+ 'pref_two_factor_auth' => 'Authenticatie in twee stappen',
+ 'pref_two_factor_auth_help' => 'Als je authenticatie in twee stappen (ook wel twee-factor authenticatie genoemd) inschakelt voeg je een extra beveiligingslaag toe aan je account. Je logt in met iets dat je weet (je wachtwoord) en iets dat je hebt (een verificatiecode). Verificatiecodes worden gegeneerd door apps op je telefoon, zoals Authy en Google Authenticator.',
+ 'pref_enable_two_factor_auth' => 'Authenticatie in twee stappen inschakelen',
+ 'pref_two_factor_auth_disabled' => 'Je verificatiecode voor authenticatie in twee stappen is verwijderd, en uitgeschakeld',
+ 'pref_two_factor_auth_remove_it' => 'Vergeet niet om je Firefly account uit je authenticatie appje te verwijderen!',
+ 'pref_two_factor_auth_code' => 'Bevestig de code',
+ 'pref_two_factor_auth_code_help' => 'Scan deze QR code met een app op je telefoon (zoals Authy of Google Authenticator). Vul de code die je terug krijgt hier in.',
+ 'pref_two_factor_auth_reset_code' => 'Reset de verificatiecode',
+ 'pref_two_factor_auth_remove_code' => 'Verwijder de verificatiecode',
+ 'pref_two_factor_auth_remove_will_disable' => '(hiermee zet je authenticatie in twee stappen ook uit)',
+ 'pref_save_settings' => 'Instellingen opslaan',
// profile:
- 'change_your_password' => 'Verander je wachtwoord',
- 'delete_account' => 'Verwijder je account',
- 'current_password' => 'Huidige wachtwoord',
- 'new_password' => 'Nieuw wachtwoord',
- 'new_password_again' => 'Nieuw wachtwoord (bevestiging)',
- 'delete_your_account' => 'Verwijder je account',
- 'delete_your_account_help' => 'Als je je account verwijdert worden ook al je rekeningen, transacties en alle andere zaken verwijderd. Alles is dan WEG.',
- 'delete_your_account_password' => 'Voer je wachtwoord in om door te gaan.',
- 'password' => 'Wachtwoord',
- 'are_you_sure' => 'Zeker weten? Je kan niet meer terug!',
- 'delete_account_button' => 'VERWIJDER je account',
- 'invalid_current_password' => 'Huidige wachtwoord is niet geldig!',
- 'password_changed' => 'Je wachtwoord is veranderd!',
- 'should_change' => 'Vul ook echt een ander wachtwoord in.',
- 'invalid_password' => 'Ongeldig wachtwoord!',
+ 'change_your_password' => 'Verander je wachtwoord',
+ 'delete_account' => 'Verwijder je account',
+ 'current_password' => 'Huidige wachtwoord',
+ 'new_password' => 'Nieuw wachtwoord',
+ 'new_password_again' => 'Nieuw wachtwoord (bevestiging)',
+ 'delete_your_account' => 'Verwijder je account',
+ 'delete_your_account_help' => 'Als je je account verwijdert worden ook al je rekeningen, transacties en alle andere zaken verwijderd. Alles is dan WEG.',
+ 'delete_your_account_password' => 'Voer je wachtwoord in om door te gaan.',
+ 'password' => 'Wachtwoord',
+ 'are_you_sure' => 'Zeker weten? Je kan niet meer terug!',
+ 'delete_account_button' => 'VERWIJDER je account',
+ 'invalid_current_password' => 'Huidige wachtwoord is niet geldig!',
+ 'password_changed' => 'Je wachtwoord is veranderd!',
+ 'should_change' => 'Vul ook echt een ander wachtwoord in.',
+ 'invalid_password' => 'Ongeldig wachtwoord!',
// attachments
- 'nr_of_attachments' => 'Eén bijlage|:count bijlagen',
- 'attachments' => 'Bijlagen',
- 'edit_attachment' => 'Wijzig bijlage ":name"',
- 'update_attachment' => 'Update bijlage',
- 'delete_attachment' => 'Verwijder bijlage ":name"',
- 'attachment_deleted' => 'Bijlage ":name" verwijderd',
- 'upload_max_file_size' => 'Maximale grootte: :size',
+ 'nr_of_attachments' => 'Eén bijlage|:count bijlagen',
+ 'attachments' => 'Bijlagen',
+ 'edit_attachment' => 'Wijzig bijlage ":name"',
+ 'update_attachment' => 'Update bijlage',
+ 'delete_attachment' => 'Verwijder bijlage ":name"',
+ 'attachment_deleted' => 'Bijlage ":name" verwijderd',
+ 'upload_max_file_size' => 'Maximale grootte: :size',
// tour:
- 'prev' => 'Vorige',
- 'next' => 'Volgende',
- 'end-tour' => 'Einde',
- 'pause' => 'Pauze',
+ 'prev' => 'Vorige',
+ 'next' => 'Volgende',
+ 'end-tour' => 'Einde',
+ 'pause' => 'Pauze',
// transaction index
- 'title_expenses' => 'Uitgaven',
- 'title_withdrawal' => 'Uitgaven',
- 'title_revenue' => 'Inkomsten',
- 'title_deposit' => 'Inkomsten',
- 'title_transfer' => 'Overboekingen',
- 'title_transfers' => 'Overboekingen',
+ 'title_expenses' => 'Uitgaven',
+ 'title_withdrawal' => 'Uitgaven',
+ 'title_revenue' => 'Inkomsten',
+ 'title_deposit' => 'Inkomsten',
+ 'title_transfer' => 'Overboekingen',
+ 'title_transfers' => 'Overboekingen',
// csv import:
- 'csv_import' => 'Importeer CSV-bestand',
- 'csv' => 'CSV',
- 'csv_index_title' => 'Upload en importeer een kommagescheiden tekstbestand',
- 'csv_define_column_roles' => 'Bepaal kolominhoud',
- 'csv_map_values' => 'Leg relaties met kolomwaardes',
- 'csv_download_config' => 'Download CSV configuratiebestand.',
- 'csv_index_text' => 'Met deze (en de komende) pagina\'s kan je kommagescheiden tekstbestanden importeren. Deze tool is gebaseerd op de prachtige tool van Atlassian. Om te beginnen selecteer je jouw tekstbestand bij "CSV-bestand". Als je hulp nodig hebt, klik dan op het -icoontje rechtsboven.',
- 'csv_index_beta_warning' => 'Deze tool is nog erg experimenteel. Wees dus voorzichtig.',
- 'csv_header_help' => 'Zet hier een vinkje als de eerste rij van het CSV-bestand de namen van de kolommen bevat',
- 'csv_date_help' => 'Het gebruikte datumformaat in jouw bestand. Gebruik het formaat zoals deze pagina het uitlegt (Engels). Het standaardformaat kan omgaan met data zoals deze: :dateExample.',
- 'csv_csv_file_help' => 'Voer hier je kommagescheiden tekstbestand in. Je kan er maar één tegelijkertijd invoeren.',
- 'csv_csv_config_file_help' => 'Voer hier je configuratiebestand in. Als je deze niet hebt, geen zorgen. Latere stappen leggen dit uit.',
- 'csv_upload_button' => 'Begin de import',
- 'csv_column_roles_title' => 'Bepaal de inhoud van elke kolom',
- 'csv_column_roles_text' => 'Firefly kan niet automatisch ontdekken wat elke kolom betekent. Je moet het zelf aangeven. Gebruik de voorbeeldgegevens als je het ook niet zeker weet. Klik op het vraagteken-icoontje (rechtsboven) om te ontdekken wat elke kolomsoort precies is. Als de kolominhoud een directe relatie heeft met gegevens die al in Firefly staan, gebruik dan het vinkje. Tijdens de volgende stap komt Firefly hier dan op terug.',
- 'csv_column_roles_table' => 'Kolominhoud',
- 'csv_column' => 'CSV-kolom',
- 'csv_column_name' => 'CSV-kolomnaam',
- 'csv_column_example' => 'Voorbeeldgegevens',
- 'csv_column_role' => 'Kolom bevat?',
- 'csv_do_map_value' => 'Directe relatie?',
- 'csv_continue' => 'Naar de volgende stap',
- 'csv_go_back' => 'Terug naar de vorige stap',
- 'csv_map_title' => 'Leg relaties met kolomwaardes',
- 'csv_map_text' => 'Sommige kolommen bevatten waardes die misschien al in Firefly bestaan. Selecteer hier de juiste combinaties zodat het importeren netjes aansluit bij je huidige gegevens.',
- 'csv_field_value' => 'Veldwaarde',
- 'csv_field_mapped_to' => 'Is gelijk aan',
- 'csv_do_not_map' => 'Geen relatie',
- 'csv_download_config_title' => 'Download importconfiguratie',
- 'csv_download_config_text' => 'Alles wat je nu hebt zitten instellen kan je downloaden als configuratiebestand voor de volgende keer. Klik op de knop om dit te doen.',
- 'csv_more_information_text' => 'Ook als het importeren fout gaat is dit bestand handig. Na het importeren krijg je nogmaals de gelegenheid dit bestand te downloaden.',
- 'csv_do_download_config' => 'Download het configuratiebestand',
- 'csv_empty_description' => '(geen omschrijving)',
- 'csv_upload_form' => 'CSV upload formulier',
- 'csv_index_unsupported_warning' => 'Het volgende wordt nog niet ondersteund:',
- 'csv_unsupported_map' => 'De tool kan de kolom ":columnRole" niet koppelen aan bestaande gegevens in de database.',
- 'csv_unsupported_value' => 'Firefly kan niet omgaan met kolommen gemarkeerd als ":columnRole".',
- 'csv_cannot_store_value' => 'Firefly heeft geen ruimte gereserveerd voor kolommen gemarkeert als ":columnRole" en kan ze helaas niet verwerken.',
- 'csv_process_title' => 'Het importeren is klaar',
- 'csv_process_text' => ':rows rijen zijn verwerkt.',
- 'csv_row' => 'Rij',
- 'csv_import_with_errors' => 'Er ging één ding fout.|Er gingen :errors dingen fout.',
- 'csv_error_see_logs' => 'De logboeken bevatten mogelijk meer details.',
- 'csv_process_new_entries' => 'Firefly heeft :imported nieuwe transactie(s) gemaakt.',
- 'csv_start_over' => 'Begin opnieuw',
- 'csv_to_index' => 'Naar de index',
- 'csv_upload_not_writeable' => 'Kan niet naar onderstaand pad schrijven. Kan dus niet uploaden.',
- 'csv_column__ignore' => '(negeer deze kolom)',
- 'csv_column_account-iban' => 'Betaalrekening (IBAN)',
- 'csv_column_account-id' => 'Betaalrekening (ID gelijk aan Firefly)',
- 'csv_column_account-name' => 'Betaalrekeningnaam',
- 'csv_column_amount' => 'Bedrag',
- 'csv_column_amount-comma-separated' => 'Bedrag (komma as decimaalscheidingsteken)',
- 'csv_column_bill-id' => 'Contract (ID gelijk aan Firefly)',
- 'csv_column_bill-name' => 'Contractnaam',
- 'csv_column_budget-id' => 'Budget (ID gelijk aan Firefly)',
- 'csv_column_budget-name' => 'Budgetnaam',
- 'csv_column_category-id' => 'Categorie (ID gelijk aan Firefly)',
- 'csv_column_category-name' => 'Categorienaam',
- 'csv_column_currency-code' => 'Valutacode (ISO 4217)',
- 'csv_column_currency-id' => 'Valuta (ID gelijk aan Firefly)',
- 'csv_column_currency-name' => 'Valutanaam',
- 'csv_column_currency-symbol' => 'Valuta',
- 'csv_column_date-rent' => 'Datum (renteberekening)',
- 'csv_column_date-transaction' => 'Datum (transactie)',
- 'csv_column_description' => 'Omschrijving',
- 'csv_column_opposing-iban' => 'Tegenrekening (IBAN)',
- 'csv_column_opposing-id' => 'Tegenrekening (ID gelijk aan Firefly)',
- 'csv_column_opposing-name' => 'Tegenrekeningnaam',
- 'csv_column_rabo-debet-credit' => 'Rabobankspecifiek bij/af indicator',
- 'csv_column_sepa-ct-id' => 'SEPA transactienummer',
- 'csv_column_sepa-ct-op' => 'SEPA tegenrekeningnummer',
- 'csv_column_sepa-db' => 'SEPA "direct debet"-nummer',
- 'csv_column_tags-comma' => 'Tags (kommagescheiden)',
- 'csv_column_tags-space' => 'Tags (spatiegescheiden)',
- 'csv_specifix_RabobankDescription' => 'Vink dit aan als je Rabobank CSV-bestanden importeert.',
- 'csv_specifix_AbnAmroDescription' => 'Vink dit aan als je ABN AMRO CSV-bestanden importeert.',
- 'csv_specifix_Dummy' => 'Dit vinkje doet niks (dummy).',
- 'csv_import_account_help' => 'Als jouw CSV bestand geen referenties bevat naar jouw rekening(en), geef dan hier aan om welke rekening het gaat.',
- 'csv_delimiter_help' => 'Kies het veldscheidingsteken dat in het invoerbestand is gebruikt. Bij twijfel is de komma de veiligste optie.',
- 'csv_date_parse_error' => 'Firefly kan van ":value" geen datum maken, gegeven het formaat ":format". Weet je zeker dat je CSV goed is?',
+ 'csv_import' => 'Importeer CSV-bestand',
+ 'csv' => 'CSV',
+ 'csv_index_title' => 'Upload en importeer een kommagescheiden tekstbestand',
+ 'csv_define_column_roles' => 'Bepaal kolominhoud',
+ 'csv_map_values' => 'Leg relaties met kolomwaardes',
+ 'csv_download_config' => 'Download CSV configuratiebestand.',
+ 'csv_index_text' => 'Met deze (en de komende) pagina\'s kan je kommagescheiden tekstbestanden importeren. Deze tool is gebaseerd op de prachtige tool van Atlassian. Om te beginnen selecteer je jouw tekstbestand bij "CSV-bestand". Als je hulp nodig hebt, klik dan op het -icoontje rechtsboven.',
+ 'csv_index_beta_warning' => 'Deze tool is nog erg experimenteel. Wees dus voorzichtig.',
+ 'csv_header_help' => 'Zet hier een vinkje als de eerste rij van het CSV-bestand de namen van de kolommen bevat',
+ 'csv_date_help' => 'Het gebruikte datumformaat in jouw bestand. Gebruik het formaat zoals deze pagina het uitlegt (Engels). Het standaardformaat kan omgaan met data zoals deze: :dateExample.',
+ 'csv_csv_file_help' => 'Voer hier je kommagescheiden tekstbestand in. Je kan er maar één tegelijkertijd invoeren.',
+ 'csv_csv_config_file_help' => 'Voer hier je configuratiebestand in. Als je deze niet hebt, geen zorgen. Latere stappen leggen dit uit.',
+ 'csv_upload_button' => 'Begin de import',
+ 'csv_column_roles_title' => 'Bepaal de inhoud van elke kolom',
+ 'csv_column_roles_text' => 'Firefly kan niet automatisch ontdekken wat elke kolom betekent. Je moet het zelf aangeven. Gebruik de voorbeeldgegevens als je het ook niet zeker weet. Klik op het vraagteken-icoontje (rechtsboven) om te ontdekken wat elke kolomsoort precies is. Als de kolominhoud een directe relatie heeft met gegevens die al in Firefly staan, gebruik dan het vinkje. Tijdens de volgende stap komt Firefly hier dan op terug.',
+ 'csv_column_roles_table' => 'Kolominhoud',
+ 'csv_column' => 'CSV-kolom',
+ 'csv_column_name' => 'CSV-kolomnaam',
+ 'csv_column_example' => 'Voorbeeldgegevens',
+ 'csv_column_role' => 'Kolom bevat?',
+ 'csv_do_map_value' => 'Directe relatie?',
+ 'csv_continue' => 'Naar de volgende stap',
+ 'csv_go_back' => 'Terug naar de vorige stap',
+ 'csv_map_title' => 'Leg relaties met kolomwaardes',
+ 'csv_map_text' => 'Sommige kolommen bevatten waardes die misschien al in Firefly bestaan. Selecteer hier de juiste combinaties zodat het importeren netjes aansluit bij je huidige gegevens.',
+ 'csv_field_value' => 'Veldwaarde',
+ 'csv_field_mapped_to' => 'Is gelijk aan',
+ 'csv_do_not_map' => 'Geen relatie',
+ 'csv_download_config_title' => 'Download importconfiguratie',
+ 'csv_download_config_text' => 'Alles wat je nu hebt zitten instellen kan je downloaden als configuratiebestand voor de volgende keer. Klik op de knop om dit te doen.',
+ 'csv_more_information_text' => 'Ook als het importeren fout gaat is dit bestand handig. Na het importeren krijg je nogmaals de gelegenheid dit bestand te downloaden.',
+ 'csv_do_download_config' => 'Download het configuratiebestand',
+ 'csv_empty_description' => '(geen omschrijving)',
+ 'csv_upload_form' => 'CSV upload formulier',
+ 'csv_index_unsupported_warning' => 'Het volgende wordt nog niet ondersteund:',
+ 'csv_unsupported_map' => 'De tool kan de kolom ":columnRole" niet koppelen aan bestaande gegevens in de database.',
+ 'csv_unsupported_value' => 'Firefly kan niet omgaan met kolommen gemarkeerd als ":columnRole".',
+ 'csv_cannot_store_value' => 'Firefly heeft geen ruimte gereserveerd voor kolommen gemarkeert als ":columnRole" en kan ze helaas niet verwerken.',
+ 'csv_process_title' => 'Het importeren is klaar',
+ 'csv_process_text' => ':rows rijen zijn verwerkt.',
+ 'csv_row' => 'Rij',
+ 'csv_import_with_errors' => 'Er ging één ding fout.|Er gingen :errors dingen fout.',
+ 'csv_error_see_logs' => 'De logboeken bevatten mogelijk meer details.',
+ 'csv_process_new_entries' => 'Firefly heeft :imported nieuwe transactie(s) gemaakt.',
+ 'csv_start_over' => 'Begin opnieuw',
+ 'csv_to_index' => 'Naar de index',
+ 'csv_upload_not_writeable' => 'Kan niet naar onderstaand pad schrijven. Kan dus niet uploaden.',
+ 'csv_column__ignore' => '(negeer deze kolom)',
+ 'csv_column_account-iban' => 'Betaalrekening (IBAN)',
+ 'csv_column_account-id' => 'Betaalrekening (ID gelijk aan Firefly)',
+ 'csv_column_account-name' => 'Betaalrekeningnaam',
+ 'csv_column_amount' => 'Bedrag',
+ 'csv_column_amount-comma-separated' => 'Bedrag (komma as decimaalscheidingsteken)',
+ 'csv_column_bill-id' => 'Contract (ID gelijk aan Firefly)',
+ 'csv_column_bill-name' => 'Contractnaam',
+ 'csv_column_budget-id' => 'Budget (ID gelijk aan Firefly)',
+ 'csv_column_budget-name' => 'Budgetnaam',
+ 'csv_column_category-id' => 'Categorie (ID gelijk aan Firefly)',
+ 'csv_column_category-name' => 'Categorienaam',
+ 'csv_column_currency-code' => 'Valutacode (ISO 4217)',
+ 'csv_column_currency-id' => 'Valuta (ID gelijk aan Firefly)',
+ 'csv_column_currency-name' => 'Valutanaam',
+ 'csv_column_currency-symbol' => 'Valuta',
+ 'csv_column_date-rent' => 'Datum (renteberekening)',
+ 'csv_column_date-transaction' => 'Datum (transactie)',
+ 'csv_column_description' => 'Omschrijving',
+ 'csv_column_opposing-iban' => 'Tegenrekening (IBAN)',
+ 'csv_column_opposing-id' => 'Tegenrekening (ID gelijk aan Firefly)',
+ 'csv_column_opposing-name' => 'Tegenrekeningnaam',
+ 'csv_column_rabo-debet-credit' => 'Rabobankspecifiek bij/af indicator',
+ 'csv_column_ing-debet-credit' => 'ING-specifieke bij/af indicator',
+ 'csv_column_sepa-ct-id' => 'SEPA transactienummer',
+ 'csv_column_sepa-ct-op' => 'SEPA tegenrekeningnummer',
+ 'csv_column_sepa-db' => 'SEPA "direct debet"-nummer',
+ 'csv_column_tags-comma' => 'Tags (kommagescheiden)',
+ 'csv_column_tags-space' => 'Tags (spatiegescheiden)',
+ 'csv_column_account-number' => 'Betaalrekening (rekeningnummer)',
+ 'csv_column_opposing-number' => 'Tegenrekening (rekeningnummer)',
+ 'csv_specifix_RabobankDescription' => 'Vink dit aan als je Rabobank CSV-bestanden importeert.',
+ 'csv_specifix_AbnAmroDescription' => 'Vink dit aan als je ABN AMRO CSV-bestanden importeert.',
+ 'csv_specifix_Dummy' => 'Dit vinkje doet niks (dummy).',
+ 'csv_import_account_help' => 'Als jouw CSV bestand geen referenties bevat naar jouw rekening(en), geef dan hier aan om welke rekening het gaat.',
+ 'csv_delimiter_help' => 'Kies het veldscheidingsteken dat in het invoerbestand is gebruikt. Bij twijfel is de komma de veiligste optie.',
+ 'csv_date_parse_error' => 'Firefly kan van ":value" geen datum maken, gegeven het formaat ":format". Weet je zeker dat je CSV goed is?',
// create new stuff:
- 'create_new_withdrawal' => 'Nieuwe uitgave',
- 'create_new_deposit' => 'Nieuwe inkomsten',
- 'create_new_transfer' => 'Nieuwe overschrijving',
- 'create_new_asset' => 'Nieuwe betaalrekening',
- 'create_new_expense' => 'Nieuwe crediteur',
- 'create_new_revenue' => 'Nieuwe debiteur',
- 'create_new_piggy_bank' => 'Nieuw spaarpotje',
- 'create_new_bill' => 'Nieuw contract',
+ 'create_new_withdrawal' => 'Nieuwe uitgave',
+ 'create_new_deposit' => 'Nieuwe inkomsten',
+ 'create_new_transfer' => 'Nieuwe overschrijving',
+ 'create_new_asset' => 'Nieuwe betaalrekening',
+ 'create_new_expense' => 'Nieuwe crediteur',
+ 'create_new_revenue' => 'Nieuwe debiteur',
+ 'create_new_piggy_bank' => 'Nieuw spaarpotje',
+ 'create_new_bill' => 'Nieuw contract',
// currencies:
- 'create_currency' => 'Voeg nieuwe valuta toe',
- 'edit_currency' => 'Wijzig valuta ":name"',
- 'store_currency' => 'Sla nieuwe valuta op',
- 'update_currency' => 'Wijzig valuta',
- 'new_default_currency' => ':name is nu de standaard valuta.',
- 'cannot_delete_currency' => 'Kan :name niet verwijderen omdat er nog transacties van zijn!',
- 'deleted_currency' => 'Valuta :name verwijderd',
- 'created_currency' => 'Nieuwe valuta :name opgeslagen',
- 'updated_currency' => 'Valuta :name bijgewerkt',
- 'ask_site_owner' => 'Vraag :owner of deze valuta wilt toevoegen, verwijderen of wijzigen.',
- 'currencies_intro' => 'Firefly III ondersteunt diverse valuta die je hier kan instellen en bewerken.',
- 'make_default_currency' => 'maak standaard',
- 'default_currency' => 'standaard',
+ 'create_currency' => 'Voeg nieuwe valuta toe',
+ 'edit_currency' => 'Wijzig valuta ":name"',
+ 'store_currency' => 'Sla nieuwe valuta op',
+ 'update_currency' => 'Wijzig valuta',
+ 'new_default_currency' => ':name is nu de standaard valuta.',
+ 'cannot_delete_currency' => 'Kan :name niet verwijderen omdat er nog transacties van zijn!',
+ 'deleted_currency' => 'Valuta :name verwijderd',
+ 'created_currency' => 'Nieuwe valuta :name opgeslagen',
+ 'updated_currency' => 'Valuta :name bijgewerkt',
+ 'ask_site_owner' => 'Vraag :owner of deze valuta wilt toevoegen, verwijderen of wijzigen.',
+ 'currencies_intro' => 'Firefly III ondersteunt diverse valuta die je hier kan instellen en bewerken.',
+ 'make_default_currency' => 'maak standaard',
+ 'default_currency' => 'standaard',
// new user:
- 'submit' => 'Invoeren',
- 'getting_started' => 'Aan de start!',
- 'to_get_started' => 'Begin met de naam van de bank waar je je betaalrekening hebt, en het saldo van die rekening.',
- 'savings_balance_text' => 'Voer ook het saldo van je spaarrekening in, als je die hebt.',
- 'cc_balance_text' => 'Als je een credit card hebt, vul dan hier je credit cardlimiet in.',
+ 'submit' => 'Invoeren',
+ 'getting_started' => 'Aan de start!',
+ 'to_get_started' => 'Begin met de naam van de bank waar je je betaalrekening hebt, en het saldo van die rekening.',
+ 'savings_balance_text' => 'Voer ook het saldo van je spaarrekening in, als je die hebt.',
+ 'cc_balance_text' => 'Als je een credit card hebt, vul dan hier je credit cardlimiet in.',
// forms:
- 'mandatoryFields' => 'Verplichte velden',
- 'optionalFields' => 'Optionele velden',
- 'options' => 'Opties',
- 'something' => 'Iets!',
+ 'mandatoryFields' => 'Verplichte velden',
+ 'optionalFields' => 'Optionele velden',
+ 'options' => 'Opties',
+ 'something' => 'Iets!',
// budgets:
- 'create_new_budget' => 'Maak een nieuw budget',
- 'store_new_budget' => 'Sla nieuw budget op',
- 'availableIn' => 'Beschikbaar in :date',
- 'transactionsWithoutBudget' => 'Uitgaven zonder budget',
- 'transactionsWithoutBudgetDate' => 'Uitgaven zonder budget in :date',
- 'createBudget' => 'Maak nieuw budget',
- 'inactiveBudgets' => 'Inactieve budgetten',
- 'without_budget_between' => 'Transacties zonder budget tussen :start en :end',
- 'budget_in_month' => ':name in :month',
- 'delete_budget' => 'Verwijder budget ":name"',
- 'edit_budget' => 'Wijzig budget ":name"',
- 'update_amount' => 'Bedrag bijwerken',
- 'update_budget' => 'Budget bijwerken',
+ 'create_new_budget' => 'Maak een nieuw budget',
+ 'store_new_budget' => 'Sla nieuw budget op',
+ 'availableIn' => 'Beschikbaar in :date',
+ 'transactionsWithoutBudget' => 'Uitgaven zonder budget',
+ 'transactionsWithoutBudgetDate' => 'Uitgaven zonder budget in :date',
+ 'createBudget' => 'Maak nieuw budget',
+ 'inactiveBudgets' => 'Inactieve budgetten',
+ 'without_budget_between' => 'Transacties zonder budget tussen :start en :end',
+ 'budget_in_month' => ':name in :month',
+ 'delete_budget' => 'Verwijder budget ":name"',
+ 'edit_budget' => 'Wijzig budget ":name"',
+ 'update_amount' => 'Bedrag bijwerken',
+ 'update_budget' => 'Budget bijwerken',
// bills:
- 'delete_bill' => 'Verwijder contract ":name"',
- 'edit_bill' => 'Wijzig contract ":name"',
- 'update_bill' => 'Wijzig contract',
- 'store_new_bill' => 'Sla nieuw contract op',
+ 'delete_bill' => 'Verwijder contract ":name"',
+ 'edit_bill' => 'Wijzig contract ":name"',
+ 'update_bill' => 'Wijzig contract',
+ 'store_new_bill' => 'Sla nieuw contract op',
// accounts:
- 'details_for_asset' => 'Overzicht voor betaalrekening ":name"',
- 'details_for_expense' => 'Overzicht voor crediteur ":name"',
- 'details_for_revenue' => 'Overzicht voor debiteur ":name"',
- 'details_for_cash' => 'Overzicht voor contant geldrekening ":name"',
- 'store_new_asset_account' => 'Sla nieuwe betaalrekening op',
- 'store_new_expense_account' => 'Sla nieuwe crediteur op',
- 'store_new_revenue_account' => 'Sla nieuwe debiteur op',
- 'edit_asset_account' => 'Wijzig betaalrekening ":name"',
- 'edit_expense_account' => 'Wijzig crediteur ":name"',
- 'edit_revenue_account' => 'Wijzig debiteur ":name"',
- 'delete_asset_account' => 'Verwijder betaalrekening ":name"',
- 'delete_expense_account' => 'Verwijder crediteur ":name"',
- 'delete_revenue_account' => 'Verwijder debiteur ":name"',
- 'asset_deleted' => 'Betaalrekening ":name" is verwijderd.',
- 'expense_deleted' => 'Crediteur ":name" is verwijderd.',
- 'revenue_deleted' => 'Debiteur ":name" is verwijderd.',
- 'update_asset_account' => 'Wijzig betaalrekening',
- 'update_expense_account' => 'Wijzig crediteur',
- 'update_revenue_account' => 'Wijzig debiteur',
- 'make_new_asset_account' => 'Nieuwe betaalrekening',
- 'make_new_expense_account' => 'Nieuwe crediteur',
- 'make_new_revenue_account' => 'Nieuwe debiteur',
- 'asset_accounts' => 'Betaalrekeningen',
- 'expense_accounts' => 'Crediteuren',
- 'revenue_accounts' => 'Debiteuren',
- 'accountExtraHelp_asset' => '',
- 'accountExtraHelp_expense' => '',
- 'accountExtraHelp_revenue' => '',
- 'account_type' => 'Rekeningtype',
- 'save_transactions_by_moving' => 'Bewaar deze transacties door ze aan een andere rekening te koppelen:',
+ 'details_for_asset' => 'Overzicht voor betaalrekening ":name"',
+ 'details_for_expense' => 'Overzicht voor crediteur ":name"',
+ 'details_for_revenue' => 'Overzicht voor debiteur ":name"',
+ 'details_for_cash' => 'Overzicht voor contant geldrekening ":name"',
+ 'store_new_asset_account' => 'Sla nieuwe betaalrekening op',
+ 'store_new_expense_account' => 'Sla nieuwe crediteur op',
+ 'store_new_revenue_account' => 'Sla nieuwe debiteur op',
+ 'edit_asset_account' => 'Wijzig betaalrekening ":name"',
+ 'edit_expense_account' => 'Wijzig crediteur ":name"',
+ 'edit_revenue_account' => 'Wijzig debiteur ":name"',
+ 'delete_asset_account' => 'Verwijder betaalrekening ":name"',
+ 'delete_expense_account' => 'Verwijder crediteur ":name"',
+ 'delete_revenue_account' => 'Verwijder debiteur ":name"',
+ 'asset_deleted' => 'Betaalrekening ":name" is verwijderd.',
+ 'expense_deleted' => 'Crediteur ":name" is verwijderd.',
+ 'revenue_deleted' => 'Debiteur ":name" is verwijderd.',
+ 'update_asset_account' => 'Wijzig betaalrekening',
+ 'update_expense_account' => 'Wijzig crediteur',
+ 'update_revenue_account' => 'Wijzig debiteur',
+ 'make_new_asset_account' => 'Nieuwe betaalrekening',
+ 'make_new_expense_account' => 'Nieuwe crediteur',
+ 'make_new_revenue_account' => 'Nieuwe debiteur',
+ 'asset_accounts' => 'Betaalrekeningen',
+ 'expense_accounts' => 'Crediteuren',
+ 'revenue_accounts' => 'Debiteuren',
+ 'accountExtraHelp_asset' => '',
+ 'accountExtraHelp_expense' => '',
+ 'accountExtraHelp_revenue' => '',
+ 'account_type' => 'Rekeningtype',
+ 'save_transactions_by_moving' => 'Bewaar deze transacties door ze aan een andere rekening te koppelen:',
// categories:
- 'new_category' => 'Nieuwe categorie',
- 'create_new_category' => 'Nieuwe categorie',
- 'without_category' => 'Zonder categorie',
- 'update_category' => 'Wijzig categorie',
- 'categories' => 'Categorieën',
- 'edit_category' => 'Wijzig categorie ":name"',
- 'no_category' => '(geen categorie)',
- 'category' => 'Categorie',
- 'delete_category' => 'Verwijder categorie ":name"',
- 'store_category' => 'Sla nieuwe categorie op',
- 'without_category_between' => 'Zonder categorie tussen :start en :end',
+ 'new_category' => 'Nieuwe categorie',
+ 'create_new_category' => 'Nieuwe categorie',
+ 'without_category' => 'Zonder categorie',
+ 'update_category' => 'Wijzig categorie',
+ 'categories' => 'Categorieën',
+ 'edit_category' => 'Wijzig categorie ":name"',
+ 'no_category' => '(geen categorie)',
+ 'category' => 'Categorie',
+ 'delete_category' => 'Verwijder categorie ":name"',
+ 'store_category' => 'Sla nieuwe categorie op',
+ 'without_category_between' => 'Zonder categorie tussen :start en :end',
// transactions:
- 'update_withdrawal' => 'Wijzig uitgave',
- 'update_deposit' => 'Wijzig inkomsten',
- 'update_transfer' => 'Wijzig overschrijving',
- 'delete_withdrawal' => 'Verwijder uitgave ":description"',
- 'delete_deposit' => 'Verwijder inkomsten ":description"',
- 'delete_transfer' => 'Verwijder overschrijving ":description"',
+ 'update_withdrawal' => 'Wijzig uitgave',
+ 'update_deposit' => 'Wijzig inkomsten',
+ 'update_transfer' => 'Wijzig overschrijving',
+ 'delete_withdrawal' => 'Verwijder uitgave ":description"',
+ 'delete_deposit' => 'Verwijder inkomsten ":description"',
+ 'delete_transfer' => 'Verwijder overschrijving ":description"',
// new user:
- 'welcome' => 'Welkom bij Firefly!',
- 'createNewAsset' => 'Maak om te beginnen een nieuwe betaalrekening .' .
- 'Hiermee kan je nieuwe transacties opslaan en beginnen met het beheren van je geld',
- 'createNewAssetButton' => 'Maak een nieuwe betaalrekening',
+ 'welcome' => 'Welkom bij Firefly!',
+ 'createNewAsset' => 'Maak om te beginnen een nieuwe betaalrekening .' .
+ 'Hiermee kan je nieuwe transacties opslaan en beginnen met het beheren van je geld',
+ 'createNewAssetButton' => 'Maak een nieuwe betaalrekening',
// home page:
- 'yourAccounts' => 'Je betaalrekeningen',
- 'budgetsAndSpending' => 'Budgetten en uitgaven',
- 'savings' => 'Sparen',
- 'markAsSavingsToContinue' => 'Om hier wat te zien stel je je betaalrekeningen in als "spaarrekening".',
- 'createPiggyToContinue' => 'Maak spaarpotjes om hier iets te zien.',
- 'newWithdrawal' => 'Nieuwe uitgave',
- 'newDeposit' => 'Nieuwe inkomsten',
- 'newTransfer' => 'Nieuwe overschrijving',
- 'moneyIn' => 'Inkomsten',
- 'moneyOut' => 'Uitgaven',
- 'billsToPay' => 'Openstaande contracten',
- 'billsPaid' => 'Betaalde contracten',
- 'viewDetails' => 'Meer info',
- 'divided' => 'verdeeld',
- 'toDivide' => 'te verdelen',
+ 'yourAccounts' => 'Je betaalrekeningen',
+ 'budgetsAndSpending' => 'Budgetten en uitgaven',
+ 'savings' => 'Sparen',
+ 'markAsSavingsToContinue' => 'Om hier wat te zien stel je je betaalrekeningen in als "spaarrekening".',
+ 'createPiggyToContinue' => 'Maak spaarpotjes om hier iets te zien.',
+ 'newWithdrawal' => 'Nieuwe uitgave',
+ 'newDeposit' => 'Nieuwe inkomsten',
+ 'newTransfer' => 'Nieuwe overschrijving',
+ 'moneyIn' => 'Inkomsten',
+ 'moneyOut' => 'Uitgaven',
+ 'billsToPay' => 'Openstaande contracten',
+ 'billsPaid' => 'Betaalde contracten',
+ 'viewDetails' => 'Meer info',
+ 'divided' => 'verdeeld',
+ 'toDivide' => 'te verdelen',
// menu and titles, should be recycled as often as possible:
- 'toggleNavigation' => 'Navigatie aan of uit',
- 'currency' => 'Valuta',
- 'preferences' => 'Voorkeuren',
- 'logout' => 'Uitloggen',
- 'searchPlaceholder' => 'Zoeken...',
- 'dashboard' => 'Dashboard',
- 'currencies' => 'Valuta',
- 'accounts' => 'Rekeningen',
- 'Asset account' => 'Betaalrekening',
- 'Default account' => 'Betaalrekening',
- 'Expense account' => 'Crediteur',
- 'Revenue account' => 'Debiteur',
- 'Initial balance account' => 'Startbalansrekening',
- 'budgets' => 'Budgetten',
- 'tags' => 'Tags',
- 'reports' => 'Overzichten',
- 'transactions' => 'Transacties',
- 'expenses' => 'Uitgaven',
- 'income' => 'Inkomsten',
- 'transfers' => 'Overschrijvingen',
- 'moneyManagement' => 'Geldbeheer',
- 'piggyBanks' => 'Spaarpotjes',
- 'bills' => 'Contracten',
- 'createNew' => 'Nieuw',
- 'withdrawal' => 'Uitgave',
- 'deposit' => 'Inkomsten',
- 'account' => 'Rekening',
- 'transfer' => 'Overschrijving',
- 'Withdrawal' => 'Uitgave',
- 'Deposit' => 'Inkomsten',
- 'Transfer' => 'Overschrijving',
- 'bill' => 'Contract',
- 'yes' => 'Ja',
- 'no' => 'Nee',
- 'amount' => 'Bedrag',
- 'newBalance' => 'Nieuw saldo',
- 'overview' => 'Overzicht',
- 'saveOnAccount' => 'Sparen op rekening',
- 'unknown' => 'Onbekend',
- 'daily' => 'Dagelijks',
- 'weekly' => 'Wekelijks',
- 'monthly' => 'Maandelijks',
- 'quarterly' => 'Elk kwartaal',
- 'half-year' => 'Elk half jaar',
- 'yearly' => 'Jaarlijks',
- 'profile' => 'Profiel',
+ 'toggleNavigation' => 'Navigatie aan of uit',
+ 'currency' => 'Valuta',
+ 'preferences' => 'Voorkeuren',
+ 'logout' => 'Uitloggen',
+ 'searchPlaceholder' => 'Zoeken...',
+ 'dashboard' => 'Dashboard',
+ 'currencies' => 'Valuta',
+ 'accounts' => 'Rekeningen',
+ 'Asset account' => 'Betaalrekening',
+ 'Default account' => 'Betaalrekening',
+ 'Expense account' => 'Crediteur',
+ 'Revenue account' => 'Debiteur',
+ 'Initial balance account' => 'Startbalansrekening',
+ 'budgets' => 'Budgetten',
+ 'tags' => 'Tags',
+ 'reports' => 'Overzichten',
+ 'transactions' => 'Transacties',
+ 'expenses' => 'Uitgaven',
+ 'income' => 'Inkomsten',
+ 'transfers' => 'Overschrijvingen',
+ 'moneyManagement' => 'Geldbeheer',
+ 'piggyBanks' => 'Spaarpotjes',
+ 'bills' => 'Contracten',
+ 'createNew' => 'Nieuw',
+ 'withdrawal' => 'Uitgave',
+ 'deposit' => 'Inkomsten',
+ 'account' => 'Rekening',
+ 'transfer' => 'Overschrijving',
+ 'Withdrawal' => 'Uitgave',
+ 'Deposit' => 'Inkomsten',
+ 'Transfer' => 'Overschrijving',
+ 'bill' => 'Contract',
+ 'yes' => 'Ja',
+ 'no' => 'Nee',
+ 'amount' => 'Bedrag',
+ 'newBalance' => 'Nieuw saldo',
+ 'overview' => 'Overzicht',
+ 'saveOnAccount' => 'Sparen op rekening',
+ 'unknown' => 'Onbekend',
+ 'daily' => 'Dagelijks',
+ 'weekly' => 'Wekelijks',
+ 'monthly' => 'Maandelijks',
+ 'quarterly' => 'Elk kwartaal',
+ 'half-year' => 'Elk half jaar',
+ 'yearly' => 'Jaarlijks',
+ 'profile' => 'Profiel',
// reports:
- 'report_default' => 'Standaard financieel rapport (:start tot :end)',
- 'quick_link_reports' => 'Snelle links',
- 'quick_link_default_report' => 'Standaard financieel rapport',
- 'report_this_month_quick' => 'Deze maand, alle rekeningen',
- 'report_this_year_quick' => 'Dit jaar, alle rekeningen',
- 'report_this_fiscal_year_quick' => 'Huidig boekjaar, alle rekeningen',
- 'report_all_time_quick' => 'Gehele periode, alle rekeningen',
- 'reports_can_bookmark' => 'Je kan rapporten aan je favorieten toevoegen.',
- 'incomeVsExpenses' => 'Inkomsten tegenover uitgaven',
- 'accountBalances' => 'Rekeningsaldi',
- 'balanceStartOfYear' => 'Saldo aan het begin van het jaar',
- 'balanceEndOfYear' => 'Saldo aan het einde van het jaar',
- 'balanceStartOfMonth' => 'Saldo aan het begin van de maand',
- 'balanceEndOfMonth' => 'Saldo aan het einde van de maand',
- 'balanceStart' => 'Saldo aan het begin van de periode',
- 'balanceEnd' => 'Saldo aan het einde van de periode',
- 'reportsOwnAccounts' => 'Overzichten voor je eigen betaalrekeningen',
- 'reportsOwnAccountsAndShared' => 'Overzichten voor je eigen betaalrekeningen en gedeelde rekeningen',
- 'splitByAccount' => 'Per betaalrekening',
- 'balancedByTransfersAndTags' => 'Gecorrigeerd met overschrijvingen en tags',
- 'coveredWithTags' => 'Gecorrigeerd met tags',
- 'leftUnbalanced' => 'Ongecorrigeerd',
- 'expectedBalance' => 'Verwacht saldo',
- 'outsideOfBudgets' => 'Buiten budgetten',
- 'leftInBudget' => 'Over van budget',
- 'sumOfSums' => 'Alles bij elkaar',
- 'noCategory' => '(zonder categorie)',
- 'notCharged' => '(Nog) niet betaald',
- 'inactive' => 'Niet actief',
- 'difference' => 'Verschil',
- 'in' => 'In',
- 'out' => 'Uit',
- 'topX' => 'top :number',
- 'showTheRest' => 'Laat alles zien',
- 'hideTheRest' => 'Laat alleen de top :number zien',
- 'sum_of_year' => 'Som van jaar',
- 'sum_of_years' => 'Som van jaren',
- 'average_of_year' => 'Gemiddelde in jaar',
- 'average_of_years' => 'Gemiddelde in jaren',
- 'categories_earned_in_year' => 'Categorieën (inkomsten)',
- 'categories_spent_in_year' => 'Categorieën (uitgaven)',
- 'report_type' => 'Rapporttype',
- 'report_type_default' => 'Standard financieel rapport',
- 'report_included_accounts' => 'Accounts in rapport',
- 'report_date_range' => 'Datumbereik',
- 'report_include_help' => 'Overboekingen naar gedeelde rekeningen tellen als uitgave. Overboekingen van gedeelde rekeningen tellen als inkomsten.',
- 'report_preset_ranges' => 'Standaardbereik',
- 'shared' => 'Gedeeld',
- 'fiscal_year' => 'Boekjaar',
+ 'report_default' => 'Standaard financieel rapport (:start tot :end)',
+ 'report_audit' => 'Transactiehistorie-overzicht van :start tot :end',
+ 'quick_link_reports' => 'Snelle links',
+ 'quick_link_default_report' => 'Standaard financieel rapport',
+ 'report_this_month_quick' => 'Deze maand, alle rekeningen',
+ 'report_this_year_quick' => 'Dit jaar, alle rekeningen',
+ 'report_this_fiscal_year_quick' => 'Huidig boekjaar, alle rekeningen',
+ 'report_all_time_quick' => 'Gehele periode, alle rekeningen',
+ 'reports_can_bookmark' => 'Je kan rapporten aan je favorieten toevoegen.',
+ 'incomeVsExpenses' => 'Inkomsten tegenover uitgaven',
+ 'accountBalances' => 'Rekeningsaldi',
+ 'balanceStartOfYear' => 'Saldo aan het begin van het jaar',
+ 'balanceEndOfYear' => 'Saldo aan het einde van het jaar',
+ 'balanceStartOfMonth' => 'Saldo aan het begin van de maand',
+ 'balanceEndOfMonth' => 'Saldo aan het einde van de maand',
+ 'balanceStart' => 'Saldo aan het begin van de periode',
+ 'balanceEnd' => 'Saldo aan het einde van de periode',
+ 'reportsOwnAccounts' => 'Overzichten voor je eigen betaalrekeningen',
+ 'reportsOwnAccountsAndShared' => 'Overzichten voor je eigen betaalrekeningen en gedeelde rekeningen',
+ 'splitByAccount' => 'Per betaalrekening',
+ 'balancedByTransfersAndTags' => 'Gecorrigeerd met overschrijvingen en tags',
+ 'coveredWithTags' => 'Gecorrigeerd met tags',
+ 'leftUnbalanced' => 'Ongecorrigeerd',
+ 'expectedBalance' => 'Verwacht saldo',
+ 'outsideOfBudgets' => 'Buiten budgetten',
+ 'leftInBudget' => 'Over van budget',
+ 'sumOfSums' => 'Alles bij elkaar',
+ 'noCategory' => '(zonder categorie)',
+ 'notCharged' => '(Nog) niet betaald',
+ 'inactive' => 'Niet actief',
+ 'difference' => 'Verschil',
+ 'in' => 'In',
+ 'out' => 'Uit',
+ 'topX' => 'top :number',
+ 'showTheRest' => 'Laat alles zien',
+ 'hideTheRest' => 'Laat alleen de top :number zien',
+ 'sum_of_year' => 'Som van jaar',
+ 'sum_of_years' => 'Som van jaren',
+ 'average_of_year' => 'Gemiddelde in jaar',
+ 'average_of_years' => 'Gemiddelde in jaren',
+ 'categories_earned_in_year' => 'Categorieën (inkomsten)',
+ 'categories_spent_in_year' => 'Categorieën (uitgaven)',
+ 'report_type' => 'Rapporttype',
+ 'report_type_default' => 'Standard financieel rapport',
+ 'report_type_audit' => 'Transactiehistorie-overzicht (audit)',
+ 'report_included_accounts' => 'Accounts in rapport',
+ 'report_date_range' => 'Datumbereik',
+ 'report_include_help' => 'Overboekingen naar gedeelde rekeningen tellen als uitgave. Overboekingen van gedeelde rekeningen tellen als inkomsten.',
+ 'report_preset_ranges' => 'Standaardbereik',
+ 'shared' => 'Gedeeld',
+ 'fiscal_year' => 'Boekjaar',
// charts:
- 'dayOfMonth' => 'Dag vd maand',
- 'month' => 'Maand',
- 'budget' => 'Budget',
- 'spent' => 'Uitgegeven',
- 'earned' => 'Verdiend',
- 'overspent' => 'Teveel uitgegeven',
- 'left' => 'Over',
- 'noBudget' => '(geen budget)',
- 'maxAmount' => 'Maximaal bedrag',
- 'minAmount' => 'Minimaal bedrag',
- 'billEntry' => 'Bedrag voor dit contract',
- 'name' => 'Naam',
- 'date' => 'Datum',
- 'paid' => 'Betaald',
- 'unpaid' => 'Niet betaald',
- 'day' => 'Dag',
- 'budgeted' => 'Gebudgetteerd',
- 'period' => 'Periode',
- 'balance' => 'Saldo',
- 'summary' => 'Samenvatting',
- 'sum' => 'Som',
- 'average' => 'Gemiddeld',
- 'balanceFor' => 'Saldo op :name',
+ 'dayOfMonth' => 'Dag vd maand',
+ 'month' => 'Maand',
+ 'budget' => 'Budget',
+ 'spent' => 'Uitgegeven',
+ 'earned' => 'Verdiend',
+ 'overspent' => 'Teveel uitgegeven',
+ 'left' => 'Over',
+ 'noBudget' => '(geen budget)',
+ 'maxAmount' => 'Maximaal bedrag',
+ 'minAmount' => 'Minimaal bedrag',
+ 'billEntry' => 'Bedrag voor dit contract',
+ 'name' => 'Naam',
+ 'date' => 'Datum',
+ 'paid' => 'Betaald',
+ 'unpaid' => 'Niet betaald',
+ 'day' => 'Dag',
+ 'budgeted' => 'Gebudgetteerd',
+ 'period' => 'Periode',
+ 'balance' => 'Saldo',
+ 'summary' => 'Samenvatting',
+ 'sum' => 'Som',
+ 'average' => 'Gemiddeld',
+ 'balanceFor' => 'Saldo op :name',
// piggy banks:
- 'piggy_bank' => 'Spaarpotje',
- 'new_piggy_bank' => 'Nieuw spaarpotje',
- 'store_piggy_bank' => 'Sla spaarpotje op',
- 'account_status' => 'Rekeningoverzicht',
- 'left_for_piggy_banks' => 'Over voor spaarpotjes',
- 'sum_of_piggy_banks' => 'Som van spaarpotjes',
- 'saved_so_far' => 'Gespaard',
- 'left_to_save' => 'Te sparen',
- 'add_money_to_piggy_title' => 'Stop geld in spaarpotje ":name"',
- 'remove_money_from_piggy_title' => 'Haal geld uit spaarpotje ":name"',
- 'add' => 'Toevoegen',
- 'remove' => 'Verwijderen',
- 'max_amount_add' => 'Hooguit toe te voegen',
- 'max_amount_remove' => 'Hooguit te verwijderen',
- 'update_piggy_button' => 'Wijzig spaarpotje',
- 'update_piggy_title' => 'Wijzig spaarpotje ":name"',
- 'details' => 'Details',
- 'events' => 'Gebeurtenissen',
- 'target_amount' => 'Doelbedrag',
- 'start_date' => 'Startdatum',
- 'target_date' => 'Doeldatum',
- 'no_target_date' => 'Geen doeldatum',
- 'todo' => 'te doen',
- 'table' => 'Tabel',
- 'piggy_bank_not_exists' => 'Dit spaarpotje bestaat niet meer.',
- 'add_any_amount_to_piggy' => 'Stop geld in dit spaarpotje om het doel van :amount te halen.',
- 'add_set_amount_to_piggy' => 'Stop voor :date :amount in dit spaarpotje om hem op tijd te vullen.',
- 'delete_piggy_bank' => 'Verwijder spaarpotje ":name"',
+ 'piggy_bank' => 'Spaarpotje',
+ 'new_piggy_bank' => 'Nieuw spaarpotje',
+ 'store_piggy_bank' => 'Sla spaarpotje op',
+ 'account_status' => 'Rekeningoverzicht',
+ 'left_for_piggy_banks' => 'Over voor spaarpotjes',
+ 'sum_of_piggy_banks' => 'Som van spaarpotjes',
+ 'saved_so_far' => 'Gespaard',
+ 'left_to_save' => 'Te sparen',
+ 'add_money_to_piggy_title' => 'Stop geld in spaarpotje ":name"',
+ 'remove_money_from_piggy_title' => 'Haal geld uit spaarpotje ":name"',
+ 'add' => 'Toevoegen',
+ 'remove' => 'Verwijderen',
+ 'max_amount_add' => 'Hooguit toe te voegen',
+ 'max_amount_remove' => 'Hooguit te verwijderen',
+ 'update_piggy_button' => 'Wijzig spaarpotje',
+ 'update_piggy_title' => 'Wijzig spaarpotje ":name"',
+ 'details' => 'Details',
+ 'events' => 'Gebeurtenissen',
+ 'target_amount' => 'Doelbedrag',
+ 'start_date' => 'Startdatum',
+ 'target_date' => 'Doeldatum',
+ 'no_target_date' => 'Geen doeldatum',
+ 'todo' => 'te doen',
+ 'table' => 'Tabel',
+ 'piggy_bank_not_exists' => 'Dit spaarpotje bestaat niet meer.',
+ 'add_any_amount_to_piggy' => 'Stop geld in dit spaarpotje om het doel van :amount te halen.',
+ 'add_set_amount_to_piggy' => 'Stop voor :date :amount in dit spaarpotje om hem op tijd te vullen.',
+ 'delete_piggy_bank' => 'Verwijder spaarpotje ":name"',
// tags
- 'regular_tag' => 'Een gewone tag.',
- 'balancing_act' => 'Er kunnen maar twee transacties worden getagged; een uitgaven en inkomsten. Ze balanceren elkaar.',
- 'advance_payment' => 'Je kan een uitgave taggen en zoveel inkomsten om de uitgave (helemaal) te compenseren.',
- 'delete_tag' => 'Verwijder tag ":tag"',
- 'new_tag' => 'Maak nieuwe tag',
- 'edit_tag' => 'Wijzig tag ":tag"',
- 'no_year' => 'Zonder jaar',
- 'no_month' => 'Zonder maand',
- 'tag_title_nothing' => 'Standaard tags',
- 'tag_title_balancingAct' => 'Balancerende tags',
- 'tag_title_advancePayment' => 'Vooruitbetaalde tags',
- 'tags_introduction' => 'Normaal gesproken zijn tags enkele woorden, gebruikt om gerelateerde zaken snel aan elkaar te plakken. dure-aanschaf, rekening, feestje. In Firefly III hebben tags meer betekenis en kan je er een datum, omschrijving en locatie aan geven. Daarmee kan je je transacties op een wat zinvollere manier aan elkaar koppelen. Je kan bijvoorbeeld een tag Kerstdiner maken en informatie over het restaurant meenemen. Zulke tags zijn enkelvoudig; je gebruikt ze maar bij één gelegenheid.',
- 'tags_group' => 'Omdat tags transacties groeperen kan je er teruggaves, vergoedingen en andere geldzaken mee aanduiden, zolang de transacties elkaar "opheffen". Hoe je dit aanpakt is aan jou. De gewone manier kan natuurlijk ook.',
- 'tags_start' => 'Maak hieronder een tag, of voer nieuwe tags in als je nieuwe transacties maakt.',
+ 'regular_tag' => 'Een gewone tag.',
+ 'balancing_act' => 'Er kunnen maar twee transacties worden getagged; een uitgaven en inkomsten. Ze balanceren elkaar.',
+ 'advance_payment' => 'Je kan een uitgave taggen en zoveel inkomsten om de uitgave (helemaal) te compenseren.',
+ 'delete_tag' => 'Verwijder tag ":tag"',
+ 'new_tag' => 'Maak nieuwe tag',
+ 'edit_tag' => 'Wijzig tag ":tag"',
+ 'no_year' => 'Zonder jaar',
+ 'no_month' => 'Zonder maand',
+ 'tag_title_nothing' => 'Standaard tags',
+ 'tag_title_balancingAct' => 'Balancerende tags',
+ 'tag_title_advancePayment' => 'Vooruitbetaalde tags',
+ 'tags_introduction' => 'Normaal gesproken zijn tags enkele woorden, gebruikt om gerelateerde zaken snel aan elkaar te plakken. dure-aanschaf, rekening, feestje. In Firefly III hebben tags meer betekenis en kan je er een datum, omschrijving en locatie aan geven. Daarmee kan je je transacties op een wat zinvollere manier aan elkaar koppelen. Je kan bijvoorbeeld een tag Kerstdiner maken en informatie over het restaurant meenemen. Zulke tags zijn enkelvoudig; je gebruikt ze maar bij één gelegenheid.',
+ 'tags_group' => 'Omdat tags transacties groeperen kan je er teruggaves, vergoedingen en andere geldzaken mee aanduiden, zolang de transacties elkaar "opheffen". Hoe je dit aanpakt is aan jou. De gewone manier kan natuurlijk ook.',
+ 'tags_start' => 'Maak hieronder een tag, of voer nieuwe tags in als je nieuwe transacties maakt.',
];
diff --git a/resources/lang/nl_NL/form.php b/resources/lang/nl_NL/form.php
old mode 100644
new mode 100755
index cce6489790..2bb5146290
--- a/resources/lang/nl_NL/form.php
+++ b/resources/lang/nl_NL/form.php
@@ -1,7 +1,13 @@
'Banknaam',
'bank_balance' => 'Saldo',
'savings_balance' => 'Saldo van spaarrekening',
@@ -37,6 +43,9 @@ return [
'revenue_account' => 'Debiteur',
'amount' => 'Bedrag',
'date' => 'Datum',
+ 'interest_date' => 'Rentedatum',
+ 'book_date' => 'Boekdatum',
+ 'process_date' => 'Verwerkingsdatum',
'category' => 'Categorie',
'tags' => 'Tags',
'deletePermanently' => 'Verwijderen',
@@ -47,6 +56,7 @@ return [
'symbol' => 'Symbool',
'code' => 'Code',
'iban' => 'IBAN',
+ 'accountNumber' => 'Rekeningnummer',
'csv' => 'CSV-bestand',
'has_headers' => 'Kolomnamen op de eerste rij?',
'date_format' => 'Datumformaat',
@@ -70,40 +80,44 @@ return [
'size' => 'Grootte',
'trigger' => 'Trigger',
'stop_processing' => 'Stop met verwerken',
-
- 'csv_comma' => 'Een komma (,)',
- 'csv_semicolon' => 'Een puntkomma (;)',
- 'csv_tab' => 'Een tab (onzichtbaar)',
-
-
- 'delete_account' => 'Verwijder rekening ":name"',
- 'delete_bill' => 'Verwijder contract ":name"',
- 'delete_budget' => 'Verwijder budget ":name"',
- 'delete_category' => 'Verwijder categorie ":name"',
- 'delete_currency' => 'Verwijder valuta ":name"',
- 'delete_journal' => 'Verwijder transactie met omschrijving ":description"',
- 'delete_attachment' => 'Verwijder bijlage ":name"',
- 'delete_rule' => 'Verwijder regel ":title"',
- 'delete_rule_group' => 'Verwijder regelgroep ":title"',
-
- 'attachment_areYouSure' => 'Weet je zeker dat je de bijlage met naam ":name" wilt verwijderen?',
- 'account_areYouSure' => 'Weet je zeker dat je de rekening met naam ":name" wilt verwijderen?',
- 'bill_areYouSure' => 'Weet je zeker dat je het contract met naam ":name" wilt verwijderen?',
- 'rule_areYouSure' => 'Weet je zeker dat je regel ":title" wilt verwijderen?',
- 'ruleGroup_areYouSure' => 'Weet je zeker dat je regelgroep ":title" wilt verwijderen?',
- 'budget_areYouSure' => 'Weet je zeker dat je het budget met naam ":name" wilt verwijderen?',
- 'category_areYouSure' => 'Weet je zeker dat je het category met naam ":name" wilt verwijderen?',
- 'currency_areYouSure' => 'Weet je zeker dat je de valuta met naam ":name" wilt verwijderen?',
- 'piggyBank_areYouSure' => 'Weet je zeker dat je het spaarpotje met naam ":name" wilt verwijderen?',
- 'journal_areYouSure' => 'Weet je zeker dat je de transactie met naam ":description" wilt verwijderen?',
- 'tag_areYouSure' => 'Weet je zeker dat je de tag met naam ":tag" wilt verwijderen?',
-
- 'permDeleteWarning' => 'Dingen verwijderen uit Firefly is permanent en kan niet ongedaan gemaakt worden.',
- 'also_delete_transactions' => 'Ook de enige transactie verbonden aan deze rekening wordt verwijderd.|Ook alle :count transacties verbonden aan deze rekening worden verwijderd.',
- 'also_delete_rules' => 'De enige regel in deze regelgroep wordt ook verwijderd.|Alle :count regels in deze regelgroep worden ook verwijderd.',
- 'also_delete_piggyBanks' => 'Ook het spaarpotje verbonden aan deze rekening wordt verwijderd.|Ook alle :count spaarpotjes verbonden aan deze rekening worden verwijderd.',
- 'bill_keep_transactions' => 'De transactie verbonden aan dit contract blijft bewaard.|De :count transacties verbonden aan dit contract blijven bewaard.',
- 'budget_keep_transactions' => 'De transactie verbonden aan dit budget blijft bewaard.|De :count transacties verbonden aan dit budget blijven bewaard.',
- 'category_keep_transactions' => 'De transactie verbonden aan deze categorie blijft bewaard.|De :count transacties verbonden aan deze categorie blijven bewaard.',
- 'tag_keep_transactions' => 'De transactie verbonden aan deze tag blijft bewaard.|De :count transacties verbonden aan deze tag blijven bewaard.',
+ 'start_date' => 'Start van bereik',
+ 'end_date' => 'Einde van bereik',
+ 'export_start_range' => 'Start van exportbereik',
+ 'export_end_range' => 'Einde van exportbereik',
+ 'export_format' => 'Bestandsformaat',
+ 'include_attachments' => 'Sla ook geüploade bijlagen op',
+ 'include_config' => 'Sla ook een configuratiebestand ook',
+ 'include_old_uploads' => 'Sla ook geïmporteerde bestanden op',
+ 'accounts' => 'Exporteer boekingen van deze rekeningen',
+ 'csv_comma' => 'Een komma (,)',
+ 'csv_semicolon' => 'Een puntkomma (;)',
+ 'csv_tab' => 'Een tab (onzichtbaar)',
+ 'delete_account' => 'Verwijder rekening ":name"',
+ 'delete_bill' => 'Verwijder contract ":name"',
+ 'delete_budget' => 'Verwijder budget ":name"',
+ 'delete_category' => 'Verwijder categorie ":name"',
+ 'delete_currency' => 'Verwijder valuta ":name"',
+ 'delete_journal' => 'Verwijder transactie met omschrijving ":description"',
+ 'delete_attachment' => 'Verwijder bijlage ":name"',
+ 'delete_rule' => 'Verwijder regel ":title"',
+ 'delete_rule_group' => 'Verwijder regelgroep ":title"',
+ 'attachment_areYouSure' => 'Weet je zeker dat je de bijlage met naam ":name" wilt verwijderen?',
+ 'account_areYouSure' => 'Weet je zeker dat je de rekening met naam ":name" wilt verwijderen?',
+ 'bill_areYouSure' => 'Weet je zeker dat je het contract met naam ":name" wilt verwijderen?',
+ 'rule_areYouSure' => 'Weet je zeker dat je regel ":title" wilt verwijderen?',
+ 'ruleGroup_areYouSure' => 'Weet je zeker dat je regelgroep ":title" wilt verwijderen?',
+ 'budget_areYouSure' => 'Weet je zeker dat je het budget met naam ":name" wilt verwijderen?',
+ 'category_areYouSure' => 'Weet je zeker dat je het category met naam ":name" wilt verwijderen?',
+ 'currency_areYouSure' => 'Weet je zeker dat je de valuta met naam ":name" wilt verwijderen?',
+ 'piggyBank_areYouSure' => 'Weet je zeker dat je het spaarpotje met naam ":name" wilt verwijderen?',
+ 'journal_areYouSure' => 'Weet je zeker dat je de transactie met naam ":description" wilt verwijderen?',
+ 'tag_areYouSure' => 'Weet je zeker dat je de tag met naam ":tag" wilt verwijderen?',
+ 'permDeleteWarning' => 'Dingen verwijderen uit Firefly is permanent en kan niet ongedaan gemaakt worden.',
+ 'also_delete_transactions' => 'Ook de enige transactie verbonden aan deze rekening wordt verwijderd.|Ook alle :count transacties verbonden aan deze rekening worden verwijderd.',
+ 'also_delete_rules' => 'De enige regel in deze regelgroep wordt ook verwijderd.|Alle :count regels in deze regelgroep worden ook verwijderd.',
+ 'also_delete_piggyBanks' => 'Ook het spaarpotje verbonden aan deze rekening wordt verwijderd.|Ook alle :count spaarpotjes verbonden aan deze rekening worden verwijderd.',
+ 'bill_keep_transactions' => 'De transactie verbonden aan dit contract blijft bewaard.|De :count transacties verbonden aan dit contract blijven bewaard.',
+ 'budget_keep_transactions' => 'De transactie verbonden aan dit budget blijft bewaard.|De :count transacties verbonden aan dit budget blijven bewaard.',
+ 'category_keep_transactions' => 'De transactie verbonden aan deze categorie blijft bewaard.|De :count transacties verbonden aan deze categorie blijven bewaard.',
+ 'tag_keep_transactions' => 'De transactie verbonden aan deze tag blijft bewaard.|De :count transacties verbonden aan deze tag blijven bewaard.',
];
diff --git a/resources/lang/nl_NL/help.php b/resources/lang/nl_NL/help.php
old mode 100644
new mode 100755
index 815b05bfc9..3cf854e3e6
--- a/resources/lang/nl_NL/help.php
+++ b/resources/lang/nl_NL/help.php
@@ -1,25 +1,29 @@
'Welkom bij Firefly III',
- 'main-content-text' => 'Doe jezelf een lol en volg deze korte tour. Je weet dan precies hoe alles werkt.',
- 'sidebar-toggle-title' => 'Sidebar om nieuwe dingen te maken',
- 'sidebar-toggle-text' => 'Verstopt onder het plusje vind je de knoppen die je nodig hebt om nieuwe dingen te maken.',
- 'account-menu-title' => 'Alle rekeningen',
- 'account-menu-text' => 'Hier vind je al je rekeningen.',
- 'budget-menu-title' => 'Budgetten',
- 'budget-menu-text' => 'Gebruik deze pagina voor budgetten.',
- 'report-menu-title' => 'Overzichten',
- 'report-menu-text' => 'Hier vind je allerlei financiele rapportages.',
- 'transaction-menu-title' => 'Transacties',
- 'transaction-menu-text' => 'Hier vind je al je bijschrijvingen, afschrijvingen en overboekingen.',
- 'option-menu-title' => 'Opties',
- 'option-menu-text' => 'Hier vind je alle opties.',
- 'main-content-end-title' => 'Einde!',
- 'main-content-end-text' => 'Elke pagina heeft een vraagtekentje rechtsboven. Gebruik deze voor meer hulp. Veel plezier!',
-
-
+ 'main-content-title' => 'Welkom bij Firefly III',
+ 'main-content-text' => 'Doe jezelf een lol en volg deze korte tour. Je weet dan precies hoe alles werkt.',
+ 'sidebar-toggle-title' => 'Sidebar om nieuwe dingen te maken',
+ 'sidebar-toggle-text' => 'Verstopt onder het plusje vind je de knoppen die je nodig hebt om nieuwe dingen te maken.',
+ 'account-menu-title' => 'Alle rekeningen',
+ 'account-menu-text' => 'Hier vind je al je rekeningen.',
+ 'budget-menu-title' => 'Budgetten',
+ 'budget-menu-text' => 'Gebruik deze pagina voor budgetten.',
+ 'report-menu-title' => 'Overzichten',
+ 'report-menu-text' => 'Hier vind je allerlei financiele rapportages.',
+ 'transaction-menu-title' => 'Transacties',
+ 'transaction-menu-text' => 'Hier vind je al je bijschrijvingen, afschrijvingen en overboekingen.',
+ 'option-menu-title' => 'Opties',
+ 'option-menu-text' => 'Hier vind je alle opties.',
+ 'main-content-end-title' => 'Einde!',
+ 'main-content-end-text' => 'Elke pagina heeft een vraagtekentje rechtsboven. Gebruik deze voor meer hulp. Veel plezier!',
'index' => 'index',
'home' => 'home',
'accounts-index' => 'rekeningen',
diff --git a/resources/lang/nl_NL/list.php b/resources/lang/nl_NL/list.php
old mode 100644
new mode 100755
index 8eb2ac36e7..4d91559b82
--- a/resources/lang/nl_NL/list.php
+++ b/resources/lang/nl_NL/list.php
@@ -1,6 +1,11 @@
'Naam',
@@ -19,6 +24,9 @@ return [
'description' => 'Omschrijving',
'amount' => 'Bedrag',
'date' => 'Datum',
+ 'interest_date' => 'Rentedatum',
+ 'book_date' => 'Boekdatum',
+ 'process_date' => 'Verwerkingsdatum',
'from' => 'Van',
'to' => 'Naar',
'budget' => 'Budget',
diff --git a/resources/lang/nl_NL/pagination.php b/resources/lang/nl_NL/pagination.php
old mode 100644
new mode 100755
index 9a2a9677a4..f6f0715d30
--- a/resources/lang/nl_NL/pagination.php
+++ b/resources/lang/nl_NL/pagination.php
@@ -1,19 +1,13 @@
'« Vorige',
'next' => 'Volgende »',
-
];
diff --git a/resources/lang/nl_NL/passwords.php b/resources/lang/nl_NL/passwords.php
old mode 100644
new mode 100755
index c8451e8ac0..13b2a25332
--- a/resources/lang/nl_NL/passwords.php
+++ b/resources/lang/nl_NL/passwords.php
@@ -8,22 +8,10 @@
*/
return [
-
- /*
- |--------------------------------------------------------------------------
- |--------------------------------------------------------------------------
- |
- | The following language lines are the default lines which match reasons
- | that are given by the password broker for a password update attempt
- | has failed, such as for an invalid token or invalid new password.
- |
- */
-
- "password" => "Wachtwoorden moeten zes karakters lang zijn, en natuurlijk 2x hetzelfde invoeren.",
- "user" => "Geen gebruiker met dat e-mailadres.",
- "token" => "Ongeldig token! Sorry",
- "sent" => "Je krijgt een mailtje met een linkje om je wachtwoord te herstellen!",
- "reset" => "Je wachtwoord is hersteld!",
+ 'password' => 'Wachtwoorden moeten zes karakters lang zijn, en natuurlijk 2x hetzelfde invoeren.',
+ 'user' => 'Geen gebruiker met dat e-mailadres.',
+ 'token' => 'Ongeldig token! Sorry.',
+ 'sent' => 'Je krijgt een mailtje met een linkje om je wachtwoord te herstellen!',
+ 'reset' => 'Je wachtwoord is hersteld!',
'blocked' => 'Leuk geprobeerd wel.',
-
];
diff --git a/resources/lang/nl_NL/validation.php b/resources/lang/nl_NL/validation.php
old mode 100644
new mode 100755
index b3da11cde3..37c25ed3d5
--- a/resources/lang/nl_NL/validation.php
+++ b/resources/lang/nl_NL/validation.php
@@ -1,69 +1,72 @@
'Deze waarde is niet geldig voor de geselecteerde trigger.',
- 'rule_action_value' => 'Deze waarde is niet geldig voor de geselecteerde actie.',
- 'invalid_domain' => 'Kan niet registereren vanaf dit domein.',
- 'file_already_attached' => 'Het geuploade bestand ":name" is al gelinkt aan deze transactie.',
- 'file_attached' => 'Bestand met naam ":name" is met succes geuploaded.',
- 'file_invalid_mime' => 'Bestand ":name" is van het type ":mime", en die kan je niet uploaden.',
- 'file_too_large' => 'Bestand ":name" is te groot.',
- "accepted" => ":attribute moet geaccepteerd zijn.",
- "active_url" => ":attribute is geen geldige URL.",
- "after" => ":attribute moet een datum na :date zijn.",
- "alpha" => ":attribute mag alleen letters bevatten.",
- "alpha_dash" => ":attribute mag alleen letters, nummers, onderstreep(_) en strepen(-) bevatten.",
- "alpha_num" => ":attribute mag alleen letters en nummers bevatten.",
- "array" => ":attribute moet geselecteerde elementen bevatten.",
- "unique_for_user" => "Er is al een entry met deze :attribute.",
- "before" => ":attribute moet een datum voor :date zijn.",
- 'unique_object_for_user' => 'Deze naam is al in gebruik',
- 'unique_account_for_user' => 'This rekeningnaam is already in use',
- "between.numeric" => ":attribute moet tussen :min en :max zijn.",
- "between.file" => ":attribute moet tussen :min en :max kilobytes zijn.",
- "between.string" => ":attribute moet tussen :min en :max karakters zijn.",
- "between.array" => ":attribute moet tussen :min en :max items bevatten.",
- "boolean" => ":attribute moet true of false zijn.",
- "confirmed" => ":attribute bevestiging komt niet overeen.",
- "date" => ":attribute moet een datum bevatten.",
- "date_format" => ":attribute moet een geldig datum formaat bevatten.",
- "different" => ":attribute en :other moeten verschillend zijn.",
- "digits" => ":attribute moet bestaan uit :digits cijfers.",
- "digits_between" => ":attribute moet bestaan uit minimaal :min en maximaal :max cijfers.",
- "email" => ":attribute is geen geldig e-mailadres.",
- "filled" => ":attribute is verplicht.",
- "exists" => ":attribute bestaat niet.",
- "image" => ":attribute moet een afbeelding zijn.",
- "in" => ":attribute is ongeldig.",
- "integer" => ":attribute moet een getal zijn.",
- "ip" => ":attribute moet een geldig IP-adres zijn.",
- 'json' => 'De :attribute moet een JSON tekst zijn.',
- "max.numeric" => ":attribute mag niet hoger dan :max zijn.",
- "max.file" => ":attribute mag niet meer dan :max kilobytes zijn.",
- "max.string" => ":attribute mag niet uit meer dan :max karakters bestaan.",
- "max.array" => ":attribute mag niet meer dan :max items bevatten.",
- "mimes" => ":attribute moet een bestand zijn van het bestandstype :values.",
- "min.numeric" => ":attribute moet minimaal :min zijn.",
- "min.file" => ":attribute moet minimaal :min kilobytes zijn.",
- "min.string" => ":attribute moet minimaal :min karakters zijn.",
- "min.array" => ":attribute moet minimaal :min items bevatten.",
- "not_in" => "Het formaat van :attribute is ongeldig.",
- "numeric" => ":attribute moet een nummer zijn.",
- "regex" => ":attribute formaat is ongeldig.",
- "required" => ":attribute is verplicht.",
- "required_if" => ":attribute is verplicht indien :other gelijk is aan :value.",
- 'required_unless' => ':attribute is verplicht tenzij :other gelijk is aan :values.',
- "required_with" => ":attribute is verplicht i.c.m. :values",
- "required_with_all" => ":attribute is verplicht i.c.m. :values",
- "required_without" => ":attribute is verplicht als :values niet ingevuld is.",
- "required_without_all" => ":attribute is verplicht als :values niet ingevuld zijn.",
- "same" => ":attribute en :other moeten overeenkomen.",
- "size.numeric" => ":attribute moet :size zijn.",
- "size.file" => ":attribute moet :size kilobyte zijn.",
- "size.string" => ":attribute moet :size karakters zijn.",
- "size.array" => ":attribute moet :size items bevatten.",
- "unique" => ":attribute is al in gebruik.",
- 'string' => 'Het :attribute moet een tekenreeks zijn.',
- "url" => ":attribute is geen geldige URL.",
- "timezone" => "Het :attribute moet een geldige zone zijn.",
+ 'iban' => 'Dit is niet een geldige IBAN.',
+ 'unique_account_number_for_user' => 'Het lijkt erop dat dit rekeningnummer al in gebruik is.',
+ 'rule_trigger_value' => 'Deze waarde is niet geldig voor de geselecteerde trigger.',
+ 'rule_action_value' => 'Deze waarde is niet geldig voor de geselecteerde actie.',
+ 'invalid_domain' => 'Kan niet registereren vanaf dit domein.',
+ 'file_already_attached' => 'Het geuploade bestand ":name" is al gelinkt aan deze transactie.',
+ 'file_attached' => 'Bestand met naam ":name" is met succes geuploaded.',
+ 'file_invalid_mime' => 'Bestand ":name" is van het type ":mime", en die kan je niet uploaden.',
+ 'file_too_large' => 'Bestand ":name" is te groot.',
+ 'accepted' => ':attribute moet geaccepteerd zijn.',
+ 'active_url' => ':attribute is geen geldige URL.',
+ 'after' => ':attribute moet een datum na :date zijn.',
+ 'alpha' => ':attribute mag alleen letters bevatten.',
+ 'alpha_dash' => ':attribute mag alleen letters, nummers, onderstreep(_) en strepen(-) bevatten.',
+ 'alpha_num' => ':attribute mag alleen letters en nummers bevatten.',
+ 'array' => ':attribute moet geselecteerde elementen bevatten.',
+ 'unique_for_user' => 'Er is al een entry met deze :attribute.',
+ 'before' => ':attribute moet een datum voor :date zijn.',
+ 'unique_object_for_user' => 'Deze naam is al in gebruik',
+ 'unique_account_for_user' => 'This rekeningnaam is already in use',
+ 'between.numeric' => ':attribute moet tussen :min en :max zijn.',
+ 'between.file' => ':attribute moet tussen :min en :max kilobytes zijn.',
+ 'between.string' => ':attribute moet tussen :min en :max karakters zijn.',
+ 'between.array' => ':attribute moet tussen :min en :max items bevatten.',
+ 'boolean' => ':attribute moet true of false zijn.',
+ 'confirmed' => ':attribute bevestiging komt niet overeen.',
+ 'date' => ':attribute moet een datum bevatten.',
+ 'date_format' => ':attribute moet een geldig datum formaat bevatten.',
+ 'different' => ':attribute en :other moeten verschillend zijn.',
+ 'digits' => ':attribute moet bestaan uit :digits cijfers.',
+ 'digits_between' => ':attribute moet bestaan uit minimaal :min en maximaal :max cijfers.',
+ 'email' => ':attribute is geen geldig e-mailadres.',
+ 'filled' => ':attribute is verplicht.',
+ 'exists' => ':attribute bestaat niet.',
+ 'image' => ':attribute moet een afbeelding zijn.',
+ 'in' => ':attribute is ongeldig.',
+ 'integer' => ':attribute moet een getal zijn.',
+ 'ip' => ':attribute moet een geldig IP-adres zijn.',
+ 'json' => 'De :attribute moet een JSON tekst zijn.',
+ 'max.numeric' => ':attribute mag niet hoger dan :max zijn.',
+ 'max.file' => ':attribute mag niet meer dan :max kilobytes zijn.',
+ 'max.string' => ':attribute mag niet uit meer dan :max karakters bestaan.',
+ 'max.array' => ':attribute mag niet meer dan :max items bevatten.',
+ 'mimes' => ':attribute moet een bestand zijn van het bestandstype :values.',
+ 'min.numeric' => ':attribute moet minimaal :min zijn.',
+ 'min.file' => ':attribute moet minimaal :min kilobytes zijn.',
+ 'min.string' => ':attribute moet minimaal :min karakters zijn.',
+ 'min.array' => ':attribute moet minimaal :min items bevatten.',
+ 'not_in' => 'Het formaat van :attribute is ongeldig.',
+ 'numeric' => ':attribute moet een nummer zijn.',
+ 'regex' => ':attribute formaat is ongeldig.',
+ 'required' => ':attribute is verplicht.',
+ 'required_if' => ':attribute is verplicht indien :other gelijk is aan :value.',
+ 'required_unless' => ':attribute is verplicht tenzij :other gelijk is aan :values.',
+ 'required_with' => ':attribute is verplicht i.c.m. :values',
+ 'required_with_all' => ':attribute is verplicht i.c.m. :values',
+ 'required_without' => ':attribute is verplicht als :values niet ingevuld is.',
+ 'required_without_all' => ':attribute is verplicht als :values niet ingevuld zijn.',
+ 'same' => ':attribute en :other moeten overeenkomen.',
+ 'size.numeric' => ':attribute moet :size zijn.',
+ 'size.file' => ':attribute moet :size kilobyte zijn.',
+ 'size.string' => ':attribute moet :size karakters zijn.',
+ 'size.array' => ':attribute moet :size items bevatten.',
+ 'unique' => ':attribute is al in gebruik.',
+ 'string' => 'Het :attribute moet een tekenreeks zijn.',
+ 'url' => ':attribute is geen geldige URL.',
+ 'timezone' => 'Het :attribute moet een geldige zone zijn.',
+ '2fa_code' => 'De waarde in het :attribute-veld is niet geldig.',
];
diff --git a/resources/lang/pt_BR/breadcrumbs.php b/resources/lang/pt_BR/breadcrumbs.php
old mode 100644
new mode 100755
index 3693e4935d..87445014c1
--- a/resources/lang/pt_BR/breadcrumbs.php
+++ b/resources/lang/pt_BR/breadcrumbs.php
@@ -1,60 +1,45 @@
'InÃcio',
-
- // accounts
'cash_accounts' => 'Contas Correntes',
'edit_account' => 'Editar conta ":name"',
-
- // currencies
'edit_currency' => 'Editar moedas ":name"',
'delete_currency' => 'Apagar moedas ":name"',
-
- // piggy banks
'newPiggyBank' => 'Criar um novo cofrinho',
'edit_piggyBank' => 'Editar cofrinho ":name"',
-
- // top menu
'preferences' => 'Preferências',
'profile' => 'Perfil',
'changePassword' => 'Alterar sua senha',
-
- // bills
'bills' => 'Faturas',
'newBill' => 'Nova fatura',
'edit_bill' => 'Editar fatura ":name"',
'delete_bill' => 'Apagar fatura ":name"',
-
- // reports
'reports' => 'Relatórios',
'monthly_report' => 'Relatório Mensal para :date',
'monthly_report_shared' => 'Relatório mensal para :date (incluindo contas compartilhadas)',
'yearly_report' => 'Relatório Anual para :date',
'yearly_report_shared' => 'Relatório anual para :date (incluindo contas compartilhadas)',
'budget_report' => 'Relatório Orçamentário para :date',
-
- // search
'searchResult' => 'Pesquisa por ":query"',
-
- // transaction lists.
'withdrawal_list' => 'Despesas',
'deposit_list' => 'Receitas, renda e depósitos',
'transfer_list' => 'Transferências',
'transfers_list' => 'Transferências',
-
- // create transactions
'create_withdrawal' => 'Criar uma nova retirada',
'create_deposit' => 'Criar um novo depósito',
'create_transfer' => 'Criar nova transferência',
-
- // edit transactions
'edit_journal' => 'Editar transação ":description"',
'delete_journal' => 'Apagar transação ":description"',
-
- // tags
'tags' => 'Etiquetas',
'createTag' => 'Criar nova etiqueta',
'edit_tag' => 'Editar etiqueta ":tag"',
'delete_tag' => 'Apagar etiqueta ":tag"',
-
];
diff --git a/resources/lang/pt_BR/config.php b/resources/lang/pt_BR/config.php
old mode 100644
new mode 100755
index 342e06a566..51fb2620dd
--- a/resources/lang/pt_BR/config.php
+++ b/resources/lang/pt_BR/config.php
@@ -1,8 +1,20 @@
'pt_BR, pt_BR.utf8',
- 'month' => '%B %Y',
- 'month_and_day' => '%e de %B de %Y',
-
+ 'locale' => 'pt_BR, pt_BR.utf8',
+ 'month' => '%B %Y',
+ 'month_and_day' => '%e de %B de %Y',
+ 'date_time' => '%B %e, %Y, @ %T',
+ 'specific_day' => '%e %B %Y',
+ 'week_in_year' => 'Week %W, %Y',
+ 'quarter_of_year' => '%B %Y',
+ 'year' => '%Y',
+ 'half_year' => '%B %Y',
];
diff --git a/resources/lang/pt_BR/firefly.php b/resources/lang/pt_BR/firefly.php
old mode 100644
new mode 100755
index 22805ae830..3cf3bc65ab
--- a/resources/lang/pt_BR/firefly.php
+++ b/resources/lang/pt_BR/firefly.php
@@ -1,111 +1,167 @@
'This language is not yet fully translated',
- 'test' => 'Você selecionou Inglês',
- 'close' => 'Fechar',
- 'pleaseHold' => 'Por favor espere...',
- 'actions' => 'Ações',
- 'edit' => 'Editar',
- 'delete' => 'Apagar',
- 'welcomeBack' => 'What\'s playing?',
- 'everything' => 'Tudo',
- 'customRange' => 'Intervalo Personalizado',
- 'apply' => 'Aplicar',
- 'cancel' => 'Cancelar',
- 'from' => 'De',
- 'to' => 'Até',
- 'total_sum' => 'Soma Total',
- 'period_sum' => 'Soma por perÃodo',
- 'showEverything' => 'Mostrar tudo',
- 'never' => 'Never',
- 'search_results_for' => 'Pesquisar resultados por ":query"',
- 'bounced_error' => 'A mensagem enviado para :email ressaltado, não tem acesso para você.',
- 'deleted_error' => 'Estas credenciais não correspondem aos nossos registros.',
- 'general_blocked_error' => 'Sua conta foi desativada, você não pode entrar.',
- 'removed_amount' => ':amount removido',
- 'added_amount' => ':amount adicionada',
- 'asset_account_role_help' => 'Quaisquer opções extras resultantes da sua escolha pode ser definido mais tarde.',
- 'Opening balance' => 'Saldo inicial',
- 'create_new_stuff' => 'Criar novas coisas',
- 'new_withdrawal' => 'Nova retirada',
- 'new_deposit' => 'Novo depósito',
- 'new_transfer' => 'Nova transferência',
- 'new_asset_account' => 'Nova conta de ativo',
- 'new_expense_account' => 'Nova conta de despesa',
- 'new_revenue_account' => 'Nova conta de receita',
- 'new_budget' => 'Novo orçamento',
- 'new_bill' => 'Nova fatura',
+ 'language_incomplete' => 'This language is not yet fully translated',
+ 'test' => 'Você selecionou Inglês',
+ 'close' => 'Fechar',
+ 'pleaseHold' => 'Por favor espere...',
+ 'actions' => 'Ações',
+ 'edit' => 'Editar',
+ 'delete' => 'Apagar',
+ 'welcomeBack' => 'What\'s playing?',
+ 'everything' => 'Tudo',
+ 'customRange' => 'Intervalo Personalizado',
+ 'apply' => 'Aplicar',
+ 'cancel' => 'Cancelar',
+ 'from' => 'De',
+ 'to' => 'Até',
+ 'total_sum' => 'Soma Total',
+ 'period_sum' => 'Soma por perÃodo',
+ 'showEverything' => 'Mostrar tudo',
+ 'never' => 'Never',
+ 'search_results_for' => 'Pesquisar resultados por ":query"',
+ 'bounced_error' => 'A mensagem enviado para :email ressaltado, não tem acesso para você.',
+ 'deleted_error' => 'Estas credenciais não correspondem aos nossos registros.',
+ 'general_blocked_error' => 'Sua conta foi desativada, você não pode entrar.',
+ 'removed_amount' => ':amount removido',
+ 'added_amount' => ':amount adicionada',
+ 'asset_account_role_help' => 'Quaisquer opções extras resultantes da sua escolha pode ser definido mais tarde.',
+ 'Opening balance' => 'Saldo inicial',
+ 'create_new_stuff' => 'Criar novas coisas',
+ 'new_withdrawal' => 'Nova retirada',
+ 'new_deposit' => 'Novo depósito',
+ 'new_transfer' => 'Nova transferência',
+ 'new_asset_account' => 'Nova conta de ativo',
+ 'new_expense_account' => 'Nova conta de despesa',
+ 'new_revenue_account' => 'Nova conta de receita',
+ 'new_budget' => 'Novo orçamento',
+ 'new_bill' => 'Nova fatura',
+ 'block_account_logout' => 'You have been logged out. Blocked accounts cannot use this site. Did you register with a valid email address?',
+ 'flash_success' => 'Success!',
+ 'flash_info' => 'Message',
+ 'flash_warning' => 'Warning!',
+ 'flash_error' => 'Error!',
+ 'flash_info_multiple' => 'There is one message|There are :count messages',
+ 'flash_error_multiple' => 'There is one error|There are :count errors',
+ 'net_worth' => 'Net worth',
+
+ // export data:
+ 'import_and_export' => 'Import and export',
+ 'export_data' => 'Export data',
+ 'export_data_intro' => 'For backup purposes, when migrating to another system or when migrating to another Firefly III installation.',
+ 'export_format' => 'Export format',
+ 'export_format_csv' => 'Comma separated values (CSV file)',
+ 'export_format_mt940' => 'MT940 compatible format',
+ 'export_included_accounts' => 'Export transactions from these accounts',
+ 'include_config_help' => 'For easy re-import into Firefly III',
+ 'include_old_uploads_help' => 'Firefly III does not throw away the original CSV files you have imported in the past. You can include them in your export.',
+ 'do_export' => 'Export',
+ 'export_status_never_started' => 'The export has not started yet',
+ 'export_status_make_exporter' => 'Creating exporter thing...',
+ 'export_status_collecting_journals' => 'Collecting your transactions...',
+ 'export_status_collected_journals' => 'Collected your transactions!',
+ 'export_status_converting_to_export_format' => 'Converting your transactions...',
+ 'export_status_converted_to_export_format' => 'Converted your transactions!',
+ 'export_status_creating_journal_file' => 'Creating the export file...',
+ 'export_status_created_journal_file' => 'Created the export file!',
+ 'export_status_collecting_attachments' => 'Collecting all your attachments...',
+ 'export_status_collected_attachments' => 'Collected all your attachments!',
+ 'export_status_collecting_old_uploads' => 'Collecting all your previous uploads...',
+ 'export_status_collected_old_uploads' => 'Collected all your previous uploads!',
+ 'export_status_creating_config_file' => 'Creating a configuration file...',
+ 'export_status_created_config_file' => 'Created a configuration file!',
+ 'export_status_creating_zip_file' => 'Creating a zip file...',
+ 'export_status_created_zip_file' => 'Created a zip file!',
+ 'export_status_finished' => 'Export has succesfully finished! Yay!',
+ 'export_data_please_wait' => 'Please wait...',
+ 'attachment_explanation' => 'The file called \':attachment_name\' (#:attachment_id) was originally uploaded to :type \':description\' (#:journal_id) dated :date for the amount of :amount.',
// rules
- 'rules' => 'Rules',
- 'rules_explanation' => 'Here you can manage rules. Rules are triggered when a transaction is created or updated. Then, if the transaction has certain properties (called "triggers") Firefly will execute the "actions". Combined, you can make Firefly respond in a certain way to new transactions.',
- 'rule_name' => 'Name of rule',
- 'rule_triggers' => 'Rule triggers when',
- 'rule_actions' => 'Rule will',
- 'new_rule' => 'New rule',
- 'new_rule_group' => 'New rule group',
- 'rule_priority_up' => 'Give rule more priority',
- 'rule_priority_down' => 'Give rule less priority',
- 'make_new_rule_group' => 'Make new rule group',
- 'store_new_rule_group' => 'Store new rule group',
- 'created_new_rule_group' => 'New rule group ":title" stored!',
- 'updated_rule_group' => 'Successfully updated rule group ":title".',
- 'edit_rule_group' => 'Edit rule group ":title"',
- 'delete_rule_group' => 'Delete rule group ":title"',
- 'deleted_rule_group' => 'Deleted rule group ":title"',
- 'update_rule_group' => 'Update rule group',
- 'no_rules_in_group' => 'There are no rules in this group',
- 'move_rule_group_up' => 'Move rule group up',
- 'move_rule_group_down' => 'Move rule group down',
- 'save_rules_by_moving' => 'Save these rule(s) by moving them to another rule group:',
- 'make_new_rule' => 'Make new rule in rule group ":title"',
- 'rule_help_stop_processing' => 'When you check this box, later rules in this group will not be executed.',
- 'rule_help_active' => 'Inactive rules will never fire.',
- 'stored_new_rule' => 'Stored new rule with title ":title"',
- 'deleted_rule' => 'Deleted rule with title ":title"',
- 'store_new_rule' => 'Store new rule',
- 'updated_rule' => 'Updated rule with title ":title"',
- 'default_rule_group_name' => 'Default rules',
- 'default_rule_group_description' => 'All your rules not in a particular group.',
- 'default_rule_name' => 'Your first default rule',
- 'default_rule_description' => 'This rule is an example. You can safely delete it.',
- 'default_rule_trigger_description' => 'The Man Who Sold the World',
- 'default_rule_trigger_from_account' => 'David Bowie',
- 'default_rule_action_prepend' => 'Bought the world from ',
- 'default_rule_action_set_category' => 'Large expenses',
-
- 'trigger' => 'Trigger',
- 'trigger_value' => 'Trigger on value',
- 'stop_processing_other_triggers' => 'Stop processing other triggers',
- 'add_rule_trigger' => 'Add new trigger',
- 'action' => 'Action',
- 'action_value' => 'Action value',
- 'stop_executing_other_actions' => 'Stop executing other actions',
- 'add_rule_action' => 'Add new action',
- 'edit_rule' => 'Edit rule ":title"',
- 'update_rule' => 'Update rule',
+ 'rules' => 'Rules',
+ 'rules_explanation' => 'Here you can manage rules. Rules are triggered when a transaction is created or updated. Then, if the transaction has certain properties (called "triggers") Firefly will execute the "actions". Combined, you can make Firefly respond in a certain way to new transactions.',
+ 'rule_name' => 'Name of rule',
+ 'rule_triggers' => 'Rule triggers when',
+ 'rule_actions' => 'Rule will',
+ 'new_rule' => 'New rule',
+ 'new_rule_group' => 'New rule group',
+ 'rule_priority_up' => 'Give rule more priority',
+ 'rule_priority_down' => 'Give rule less priority',
+ 'make_new_rule_group' => 'Make new rule group',
+ 'store_new_rule_group' => 'Store new rule group',
+ 'created_new_rule_group' => 'New rule group ":title" stored!',
+ 'updated_rule_group' => 'Successfully updated rule group ":title".',
+ 'edit_rule_group' => 'Edit rule group ":title"',
+ 'delete_rule_group' => 'Delete rule group ":title"',
+ 'deleted_rule_group' => 'Deleted rule group ":title"',
+ 'update_rule_group' => 'Update rule group',
+ 'no_rules_in_group' => 'There are no rules in this group',
+ 'move_rule_group_up' => 'Move rule group up',
+ 'move_rule_group_down' => 'Move rule group down',
+ 'save_rules_by_moving' => 'Save these rule(s) by moving them to another rule group:',
+ 'make_new_rule' => 'Make new rule in rule group ":title"',
+ 'rule_help_stop_processing' => 'When you check this box, later rules in this group will not be executed.',
+ 'rule_help_active' => 'Inactive rules will never fire.',
+ 'stored_new_rule' => 'Stored new rule with title ":title"',
+ 'deleted_rule' => 'Deleted rule with title ":title"',
+ 'store_new_rule' => 'Store new rule',
+ 'updated_rule' => 'Updated rule with title ":title"',
+ 'default_rule_group_name' => 'Default rules',
+ 'default_rule_group_description' => 'All your rules not in a particular group.',
+ 'default_rule_name' => 'Your first default rule',
+ 'default_rule_description' => 'This rule is an example. You can safely delete it.',
+ 'default_rule_trigger_description' => 'The Man Who Sold the World',
+ 'default_rule_trigger_from_account' => 'David Bowie',
+ 'default_rule_action_prepend' => 'Bought the world from ',
+ 'default_rule_action_set_category' => 'Large expenses',
+ 'trigger' => 'Trigger',
+ 'trigger_value' => 'Trigger on value',
+ 'stop_processing_other_triggers' => 'Stop processing other triggers',
+ 'add_rule_trigger' => 'Add new trigger',
+ 'action' => 'Action',
+ 'action_value' => 'Action value',
+ 'stop_executing_other_actions' => 'Stop executing other actions',
+ 'add_rule_action' => 'Add new action',
+ 'edit_rule' => 'Edit rule ":title"',
+ 'delete_rule' => 'Delete rule ":title"',
+ 'update_rule' => 'Update rule',
+ 'test_rule_triggers' => 'See matching transactions',
+ 'warning_transaction_subset' => 'For performance reasons this list is limited to :max_num_transactions and may only show a subset of matching transactions',
+ 'warning_no_matching_transactions' => 'No matching transactions found. Please note that for performance reasons, only the last :num_transactions transactions have been checked.',
+ 'warning_no_valid_triggers' => 'No valid triggers provided.',
+ 'execute_on_existing_transactions' => 'Execute for existing transactions',
+ 'execute_on_existing_transactions_intro' => 'When a rule or group has been changed or added, you can execute it for existing transactions',
+ 'execute_on_existing_transactions_short' => 'Existing transactions',
+ 'executed_group_on_existing_transactions' => 'Executed group ":title" for existing transactions',
+ 'execute_group_on_existing_transactions' => 'Execute group ":title" for existing transactions',
+ 'include_transactions_from_accounts' => 'Include transactions from these accounts',
+ 'execute' => 'Execute',
// actions and triggers
- 'rule_trigger_user_action' => 'User action is ":trigger_value"',
- 'rule_trigger_from_account_starts' => 'Source account starts with ":trigger_value"',
- 'rule_trigger_from_account_ends' => 'Source account ends with ":trigger_value"',
- 'rule_trigger_from_account_is' => 'Source account is ":trigger_value"',
- 'rule_trigger_from_account_contains' => 'Source account contains ":trigger_value"',
- 'rule_trigger_to_account_starts' => 'Destination account starts with ":trigger_value"',
- 'rule_trigger_to_account_ends' => 'Destination account ends with ":trigger_value"',
- 'rule_trigger_to_account_is' => 'Destination account is ":trigger_value"',
- 'rule_trigger_to_account_contains' => 'Destination account contains ":trigger_value"',
- 'rule_trigger_transaction_type' => 'Transaction is of type ":trigger_value"',
- 'rule_trigger_amount_less' => 'Amount is less than :trigger_value',
- 'rule_trigger_amount_exactly' => 'Amount is :trigger_value',
- 'rule_trigger_amount_more' => 'Amount is more than :trigger_value',
- 'rule_trigger_description_starts' => 'Description starts with ":trigger_value"',
- 'rule_trigger_description_ends' => 'Description ends with ":trigger_value"',
- 'rule_trigger_description_contains' => 'Description contains ":trigger_value"',
- 'rule_trigger_description_is' => 'Description is ":trigger_value"',
-
+ 'rule_trigger_user_action' => 'User action is ":trigger_value"',
+ 'rule_trigger_from_account_starts' => 'Source account starts with ":trigger_value"',
+ 'rule_trigger_from_account_ends' => 'Source account ends with ":trigger_value"',
+ 'rule_trigger_from_account_is' => 'Source account is ":trigger_value"',
+ 'rule_trigger_from_account_contains' => 'Source account contains ":trigger_value"',
+ 'rule_trigger_to_account_starts' => 'Destination account starts with ":trigger_value"',
+ 'rule_trigger_to_account_ends' => 'Destination account ends with ":trigger_value"',
+ 'rule_trigger_to_account_is' => 'Destination account is ":trigger_value"',
+ 'rule_trigger_to_account_contains' => 'Destination account contains ":trigger_value"',
+ 'rule_trigger_transaction_type' => 'Transaction is of type ":trigger_value"',
+ 'rule_trigger_amount_less' => 'Amount is less than :trigger_value',
+ 'rule_trigger_amount_exactly' => 'Amount is :trigger_value',
+ 'rule_trigger_amount_more' => 'Amount is more than :trigger_value',
+ 'rule_trigger_description_starts' => 'Description starts with ":trigger_value"',
+ 'rule_trigger_description_ends' => 'Description ends with ":trigger_value"',
+ 'rule_trigger_description_contains' => 'Description contains ":trigger_value"',
+ 'rule_trigger_description_is' => 'Description is ":trigger_value"',
'rule_trigger_from_account_starts_choice' => 'Source account starts with..',
'rule_trigger_from_account_ends_choice' => 'Source account ends with..',
'rule_trigger_from_account_is_choice' => 'Source account is..',
@@ -122,486 +178,497 @@ return [
'rule_trigger_description_ends_choice' => 'Description ends with..',
'rule_trigger_description_contains_choice' => 'Description contains..',
'rule_trigger_description_is_choice' => 'Description is..',
-
- 'rule_trigger_store_journal' => 'When a journal is created',
- 'rule_trigger_update_journal' => 'When a journal is updated',
-
- 'rule_action_set_category' => 'Set category to ":action_value"',
- 'rule_action_clear_category' => 'Clear category',
- 'rule_action_set_budget' => 'Set budget to ":action_value"',
- 'rule_action_clear_budget' => 'Clear budget',
- 'rule_action_add_tag' => 'Add tag ":action_value"',
- 'rule_action_remove_tag' => 'Remove tag ":action_value"',
- 'rule_action_remove_all_tags' => 'Remove all tags',
- 'rule_action_set_description' => 'Set description to ":action_value"',
- 'rule_action_append_description' => 'Append description with ":action_value"',
- 'rule_action_prepend_description' => 'Prepend description with ":action_value"',
-
- 'rule_action_set_category_choice' => 'Set category to..',
- 'rule_action_clear_category_choice' => 'Clear any category',
- 'rule_action_set_budget_choice' => 'Set budget to..',
- 'rule_action_clear_budget_choice' => 'Clear any budget',
- 'rule_action_add_tag_choice' => 'Add tag..',
- 'rule_action_remove_tag_choice' => 'Remove tag..',
- 'rule_action_remove_all_tags_choice' => 'Remove all tags',
- 'rule_action_set_description_choice' => 'Set description to..',
- 'rule_action_append_description_choice' => 'Append description with..',
- 'rule_action_prepend_description_choice' => 'Prepend description with..',
+ 'rule_trigger_store_journal' => 'When a journal is created',
+ 'rule_trigger_update_journal' => 'When a journal is updated',
+ 'rule_action_set_category' => 'Set category to ":action_value"',
+ 'rule_action_clear_category' => 'Clear category',
+ 'rule_action_set_budget' => 'Set budget to ":action_value"',
+ 'rule_action_clear_budget' => 'Clear budget',
+ 'rule_action_add_tag' => 'Add tag ":action_value"',
+ 'rule_action_remove_tag' => 'Remove tag ":action_value"',
+ 'rule_action_remove_all_tags' => 'Remove all tags',
+ 'rule_action_set_description' => 'Set description to ":action_value"',
+ 'rule_action_append_description' => 'Append description with ":action_value"',
+ 'rule_action_prepend_description' => 'Prepend description with ":action_value"',
+ 'rule_action_set_category_choice' => 'Set category to..',
+ 'rule_action_clear_category_choice' => 'Clear any category',
+ 'rule_action_set_budget_choice' => 'Set budget to..',
+ 'rule_action_clear_budget_choice' => 'Clear any budget',
+ 'rule_action_add_tag_choice' => 'Add tag..',
+ 'rule_action_remove_tag_choice' => 'Remove tag..',
+ 'rule_action_remove_all_tags_choice' => 'Remove all tags',
+ 'rule_action_set_description_choice' => 'Set description to..',
+ 'rule_action_append_description_choice' => 'Append description with..',
+ 'rule_action_prepend_description_choice' => 'Prepend description with..',
// tags
- 'store_new_tag' => 'Armazenar nova tag',
- 'update_tag' => 'Atualizar tag',
- 'no_location_set' => 'Nenhuma localização.',
- 'meta_data' => 'Meta dados',
- 'location' => 'Localização',
+ 'store_new_tag' => 'Armazenar nova tag',
+ 'update_tag' => 'Atualizar tag',
+ 'no_location_set' => 'Nenhuma localização.',
+ 'meta_data' => 'Meta dados',
+ 'location' => 'Localização',
// preferences
- 'pref_home_screen_accounts' => 'Conta da tela inicial',
- 'pref_home_screen_accounts_help' => 'Que conta deve ser exibida na tela inicial?',
- 'pref_budget_settings' => 'Definições de Orçamento',
- 'pref_budget_settings_help' => 'Qual a quantidade máxima de dinheiro um envelope orçamental pode conter?',
- 'pref_view_range' => 'Ver intervalo',
- 'pref_view_range_help' => 'Alguns gráficos são agrupados automaticamente em perÃodos. Qual perÃodo você prefere?',
- 'pref_1D' => 'Um dia',
- 'pref_1W' => 'Uma semana',
- 'pref_1M' => 'Um mês',
- 'pref_3M' => 'Trimestral',
- 'pref_6M' => 'Semestral',
- 'pref_languages' => 'Idiomas',
- 'pref_languages_help' => 'Firefly III suporta muitos idiomas. Qual você prefere?',
- 'pref_custom_fiscal_year' => 'Fiscal year settings',
- 'pref_custom_fiscal_year_label' => 'Enabled',
- 'pref_custom_fiscal_year_help' => 'In countries that use a financial year other than January 1 to December 31, you can switch this on and specify start / end days of the fiscal year',
- 'pref_fiscal_year_start_label' => 'Fiscal year start date',
- 'pref_save_settings' => 'Salvar definições',
+ 'pref_home_screen_accounts' => 'Conta da tela inicial',
+ 'pref_home_screen_accounts_help' => 'Que conta deve ser exibida na tela inicial?',
+ 'pref_budget_settings' => 'Definições de Orçamento',
+ 'pref_budget_settings_help' => 'Qual a quantidade máxima de dinheiro um envelope orçamental pode conter?',
+ 'pref_view_range' => 'Ver intervalo',
+ 'pref_view_range_help' => 'Alguns gráficos são agrupados automaticamente em perÃodos. Qual perÃodo você prefere?',
+ 'pref_1D' => 'Um dia',
+ 'pref_1W' => 'Uma semana',
+ 'pref_1M' => 'Um mês',
+ 'pref_3M' => 'Trimestral',
+ 'pref_6M' => 'Semestral',
+ 'pref_languages' => 'Idiomas',
+ 'pref_languages_help' => 'Firefly III suporta muitos idiomas. Qual você prefere?',
+ 'pref_custom_fiscal_year' => 'Fiscal year settings',
+ 'pref_custom_fiscal_year_label' => 'Enabled',
+ 'pref_custom_fiscal_year_help' => 'In countries that use a financial year other than January 1 to December 31, you can switch this on and specify start / end days of the fiscal year',
+ 'pref_fiscal_year_start_label' => 'Fiscal year start date',
+ 'pref_two_factor_auth' => '2-step verification',
+ 'pref_two_factor_auth_help' => 'When you enable 2-step verification (also known as two-factor authentication), you add an extra layer of security to your account. You sign in with something you know (your password) and something you have (a verification code). Verification codes are generated by an application on your phone, such as Authy or Google Authenticator.',
+ 'pref_enable_two_factor_auth' => 'Enable 2-step verification',
+ 'pref_two_factor_auth_disabled' => '2-step verification code removed and disabled',
+ 'pref_two_factor_auth_remove_it' => 'Don\'t forget to remove the account from your authentication app!',
+ 'pref_two_factor_auth_code' => 'Verify code',
+ 'pref_two_factor_auth_code_help' => 'Scan the QR code with an application on your phone such as Authy or Google Authenticator and enter the generated code.',
+ 'pref_two_factor_auth_reset_code' => 'Reset verification code',
+ 'pref_two_factor_auth_remove_code' => 'Remove verification code',
+ 'pref_two_factor_auth_remove_will_disable' => '(this will also disable two-factor authentication)',
+ 'pref_save_settings' => 'Salvar definições',
// profile:
- 'change_your_password' => 'Alterar sua senha',
- 'delete_account' => 'Apagar conta',
- 'current_password' => 'Senha atual',
- 'new_password' => 'Nova senha',
- 'new_password_again' => 'Nova senha (novamente)',
- 'delete_your_account' => 'Apagar sua conta',
- 'delete_your_account_help' => 'Deleting your account will also delete any accounts, transactions, anything you might have saved into Firefly III. It\'ll be GONE.',
- 'delete_your_account_password' => 'Coloque sua senha para continuar.',
- 'password' => 'Senha',
- 'are_you_sure' => 'Você tem certeza? Você não poderá desfazer isso.',
- 'delete_account_button' => 'Apagar sua conta',
- 'invalid_current_password' => 'Senha atual inválida!',
- 'password_changed' => 'Senha alterada!',
- 'should_change' => 'A idéia é alterar sua senha.',
- 'invalid_password' => 'Senha inválida!',
-
+ 'change_your_password' => 'Alterar sua senha',
+ 'delete_account' => 'Apagar conta',
+ 'current_password' => 'Senha atual',
+ 'new_password' => 'Nova senha',
+ 'new_password_again' => 'Nova senha (novamente)',
+ 'delete_your_account' => 'Apagar sua conta',
+ 'delete_your_account_help' => 'Deleting your account will also delete any accounts, transactions, anything you might have saved into Firefly III. It\'ll be GONE.',
+ 'delete_your_account_password' => 'Coloque sua senha para continuar.',
+ 'password' => 'Senha',
+ 'are_you_sure' => 'Você tem certeza? Você não poderá desfazer isso.',
+ 'delete_account_button' => 'Apagar sua conta',
+ 'invalid_current_password' => 'Senha atual inválida!',
+ 'password_changed' => 'Senha alterada!',
+ 'should_change' => 'A idéia é alterar sua senha.',
+ 'invalid_password' => 'Senha inválida!',
// attachments
- 'nr_of_attachments' => 'Um anexo|:count anexos',
- 'attachments' => 'Anexos',
- 'edit_attachment' => 'Editar anexo ":name"',
- 'update_attachment' => 'Atualizar anexo',
- 'delete_attachment' => 'Apagar anexo ":name"',
- 'attachment_deleted' => 'Anexo apagado ":name"',
- 'upload_max_file_size' => 'Tamanho máximo do arquivo: :size',
+ 'nr_of_attachments' => 'Um anexo|:count anexos',
+ 'attachments' => 'Anexos',
+ 'edit_attachment' => 'Editar anexo ":name"',
+ 'update_attachment' => 'Atualizar anexo',
+ 'delete_attachment' => 'Apagar anexo ":name"',
+ 'attachment_deleted' => 'Anexo apagado ":name"',
+ 'upload_max_file_size' => 'Tamanho máximo do arquivo: :size',
// tour:
- 'prev' => 'Anterior',
- 'next' => 'Próximo',
- 'end-tour' => 'Fim do Tour',
- 'pause' => 'Parar',
+ 'prev' => 'Anterior',
+ 'next' => 'Próximo',
+ 'end-tour' => 'Fim do Tour',
+ 'pause' => 'Parar',
// transaction index
- 'title_expenses' => 'Despesas',
- 'title_withdrawal' => 'Despesas',
- 'title_revenue' => 'Receitas / Renda',
- 'title_deposit' => 'Receita / Renda',
- 'title_transfer' => 'Transferências',
- 'title_transfers' => 'Transferências',
+ 'title_expenses' => 'Despesas',
+ 'title_withdrawal' => 'Despesas',
+ 'title_revenue' => 'Receitas / Renda',
+ 'title_deposit' => 'Receita / Renda',
+ 'title_transfer' => 'Transferências',
+ 'title_transfers' => 'Transferências',
// csv import:
- 'csv_import' => 'Importar arquivo CSV',
- 'csv' => 'CSV',
- 'csv_index_title' => 'Carregar e importar um arquivo CSV',
- 'csv_define_column_roles' => 'Definir papeis da coluna',
- 'csv_map_values' => 'Valores mapeados encontrados para valores existentes',
- 'csv_download_config' => 'Download do arquivo CSV de configuração.',
- 'csv_index_text' => 'This form allows you to import a CSV file with transactions into Firefly. It is based on the excellent CSV importer made by the folks at Atlassian. Simply upload your CSV file and follow the instructions. If you would like to learn more, please click on the button at the top of this page.',
- 'csv_index_beta_warning' => 'Esta ferramenta está em beta. Por favor proceder com cautela',
- 'csv_header_help' => 'Check this box when your CSV file\'s first row consists of column names, not actual data',
- 'csv_date_help' => 'Date time format in your CSV. Follow the format like this page indicates. The default value will parse dates that look like this: :dateExample.',
- 'csv_csv_file_help' => 'Select the CSV file here. You can only upload one file at a time',
- 'csv_csv_config_file_help' => 'Select your CSV import configuration here. If you do not know what this is, ignore it. It will be explained later.',
- 'csv_upload_button' => 'Iniciando importação do CSV',
- 'csv_column_roles_title' => 'Definir papeis da coluna',
- 'csv_column_roles_text' => 'Firefly does not know what each column means. You need to indicate what every column is. Please check out the example data if you\'re not sure yourself. Click on the question mark (top right of the page) to learn what each column means. If you want to map imported data onto existing data in Firefly, use the checkbox. The next step will show you what this button does.',
- 'csv_column_roles_table' => 'Papéis da Coluna',
- 'csv_column' => 'Coluna CSV',
- 'csv_column_name' => 'Nome da coluna do CSV',
- 'csv_column_example' => 'Exemplo de dados da coluna',
- 'csv_column_role' => 'Coluna contém?',
- 'csv_do_map_value' => 'Valor mapeado?',
- 'csv_continue' => 'Continuar para o próximo passo',
- 'csv_go_back' => 'Voltar para o passo anterior',
- 'csv_map_title' => 'Valores mapeados encontrados para valores existentes',
- 'csv_map_text' => 'This page allows you to map the values from the CSV file to existing entries in your database. This ensures that accounts and other things won\'t be created twice.',
- 'csv_field_value' => 'Valor do campo do CSV',
- 'csv_field_mapped_to' => 'Deve ser mapeado para...',
- 'csv_do_not_map' => 'Não mapear este valor',
- 'csv_download_config_title' => 'Download do CSV de configuração ',
- 'csv_download_config_text' => 'Everything you\'ve just set up can be downloaded as a configuration file. Click the button to do so.',
- 'csv_more_information_text' => 'If the import fails, you can use this configuration file so you don\'t have to start all over again. But, if the import succeeds, it will be easier to upload similar CSV files.',
- 'csv_do_download_config' => 'Download do arquivo de configuração.',
- 'csv_empty_description' => '(descrição vazia)',
- 'csv_upload_form' => 'Formulário de Upload do CSV',
- 'csv_index_unsupported_warning' => 'O importador de CSV está incapaz de fazer o seguinte:',
- 'csv_unsupported_map' => 'The importer cannot map the column ":columnRole" to existing values in the database.',
- 'csv_unsupported_value' => 'The importer does not know how to handle values in columns marked as ":columnRole".',
- 'csv_cannot_store_value' => 'The importer has not reserved space for columns marked ":columnRole" and will be incapable of processing them.',
- 'csv_process_title' => 'Importação do CSV terminou!',
- 'csv_process_text' => 'O importador do CSV terminou e processou :rows linhas',
- 'csv_row' => 'Linha',
- 'csv_import_with_errors' => 'Houve um erro.|Houve :errors erros.',
- 'csv_error_see_logs' => 'Verifique o arquivo de log para ver detalhes.',
- 'csv_process_new_entries' => 'Firefly criou :imported nova(s) transação(ões)',
- 'csv_start_over' => 'Importar novamente',
- 'csv_to_index' => 'Voltar para tela inicial',
- 'csv_upload_not_writeable' => 'Cannot write to the path mentioned here. Cannot upload',
- 'csv_column__ignore' => '(ignorar esta coluna)',
- 'csv_column_account-iban' => 'Conta de Ativo (IBAN)',
- 'csv_column_account-id' => 'ID da Conta de Ativo (correspondente Firefly)',
- 'csv_column_account-name' => 'Conta de Ativo (nome)',
- 'csv_column_amount' => 'Valor',
- 'csv_column_amount-comma-separated' => 'Amount (comma as decimal separator)',
- 'csv_column_bill-id' => 'ID Fatura (correspondente Firefly)',
- 'csv_column_bill-name' => 'Nom da Fatura',
- 'csv_column_budget-id' => 'ID do Orçamento (correspondente Firefly)',
- 'csv_column_budget-name' => 'Nome do Orçamento',
- 'csv_column_category-id' => 'ID da Categoria (correspondente Firefly)',
- 'csv_column_category-name' => 'Nome da Categoria',
- 'csv_column_currency-code' => 'Código da Moeda (ISO 4217)',
- 'csv_column_currency-id' => 'ID da Moeda (correspondente Firefly)',
- 'csv_column_currency-name' => 'Nome da Moeda (correspondente Firefly)',
- 'csv_column_currency-symbol' => 'SÃmbolo da Moeda (correspondente Firefly)',
- 'csv_column_date-rent' => 'Rent calculation date',
- 'csv_column_date-transaction' => 'Data',
- 'csv_column_description' => 'Descrição',
- 'csv_column_opposing-iban' => 'Opposing account (IBAN)',
- 'csv_column_opposing-id' => 'Opposing account ID (matching Firefly)',
- 'csv_column_opposing-name' => 'Opposing account (name)',
- 'csv_column_rabo-debet-credit' => 'Rabobank specific debet/credit indicator',
- 'csv_column_sepa-ct-id' => 'SEPA Credit Transfer end-to-end ID',
- 'csv_column_sepa-ct-op' => 'SEPA Credit Transfer opposing account',
- 'csv_column_sepa-db' => 'SEPA Direct Debet',
- 'csv_column_tags-comma' => 'Tags (separadas por vÃrgula)',
- 'csv_column_tags-space' => 'Tags (separadas por espaço)',
- 'csv_specifix_RabobankDescription' => 'Select this when you\'re importing Rabobank CSV export files.',
- 'csv_specifix_AbnAmroDescription' => 'Select this when you\'re importing ABN AMRO CSV export files.',
- 'csv_specifix_Dummy' => 'Checking this has no effect whatsoever.',
- 'csv_import_account_help' => 'If your CSV file does NOT contain information about your asset account(s), use this dropdown to select to which account the transactions in the CSV belong to.',
- 'csv_delimiter_help' => 'Choose the field delimiter that is used in your input file. If not sure, comma is the safest option.',
- 'csv_date_parse_error' => 'Could not parse a valid date from ":value", using the format ":format". Are you sure your CSV is correct?',
+ 'csv_import' => 'Importar arquivo CSV',
+ 'csv' => 'CSV',
+ 'csv_index_title' => 'Carregar e importar um arquivo CSV',
+ 'csv_define_column_roles' => 'Definir papeis da coluna',
+ 'csv_map_values' => 'Valores mapeados encontrados para valores existentes',
+ 'csv_download_config' => 'Download do arquivo CSV de configuração.',
+ 'csv_index_text' => 'This form allows you to import a CSV file with transactions into Firefly. It is based on the excellent CSV importer made by the folks at Atlassian. Simply upload your CSV file and follow the instructions. If you would like to learn more, please click on the button at the top of this page.',
+ 'csv_index_beta_warning' => 'Esta ferramenta está em beta. Por favor proceder com cautela',
+ 'csv_header_help' => 'Check this box when your CSV file\'s first row consists of column names, not actual data',
+ 'csv_date_help' => 'Date time format in your CSV. Follow the format like this page indicates. The default value will parse dates that look like this: :dateExample.',
+ 'csv_csv_file_help' => 'Select the CSV file here. You can only upload one file at a time',
+ 'csv_csv_config_file_help' => 'Select your CSV import configuration here. If you do not know what this is, ignore it. It will be explained later.',
+ 'csv_upload_button' => 'Iniciando importação do CSV',
+ 'csv_column_roles_title' => 'Definir papeis da coluna',
+ 'csv_column_roles_text' => 'Firefly does not know what each column means. You need to indicate what every column is. Please check out the example data if you\'re not sure yourself. Click on the question mark (top right of the page) to learn what each column means. If you want to map imported data onto existing data in Firefly, use the checkbox. The next step will show you what this button does.',
+ 'csv_column_roles_table' => 'Papéis da Coluna',
+ 'csv_column' => 'Coluna CSV',
+ 'csv_column_name' => 'Nome da coluna do CSV',
+ 'csv_column_example' => 'Exemplo de dados da coluna',
+ 'csv_column_role' => 'Coluna contém?',
+ 'csv_do_map_value' => 'Valor mapeado?',
+ 'csv_continue' => 'Continuar para o próximo passo',
+ 'csv_go_back' => 'Voltar para o passo anterior',
+ 'csv_map_title' => 'Valores mapeados encontrados para valores existentes',
+ 'csv_map_text' => 'This page allows you to map the values from the CSV file to existing entries in your database. This ensures that accounts and other things won\'t be created twice.',
+ 'csv_field_value' => 'Valor do campo do CSV',
+ 'csv_field_mapped_to' => 'Deve ser mapeado para...',
+ 'csv_do_not_map' => 'Não mapear este valor',
+ 'csv_download_config_title' => 'Download do CSV de configuração ',
+ 'csv_download_config_text' => 'Everything you\'ve just set up can be downloaded as a configuration file. Click the button to do so.',
+ 'csv_more_information_text' => 'If the import fails, you can use this configuration file so you don\'t have to start all over again. But, if the import succeeds, it will be easier to upload similar CSV files.',
+ 'csv_do_download_config' => 'Download do arquivo de configuração.',
+ 'csv_empty_description' => '(descrição vazia)',
+ 'csv_upload_form' => 'Formulário de Upload do CSV',
+ 'csv_index_unsupported_warning' => 'O importador de CSV está incapaz de fazer o seguinte:',
+ 'csv_unsupported_map' => 'The importer cannot map the column ":columnRole" to existing values in the database.',
+ 'csv_unsupported_value' => 'The importer does not know how to handle values in columns marked as ":columnRole".',
+ 'csv_cannot_store_value' => 'The importer has not reserved space for columns marked ":columnRole" and will be incapable of processing them.',
+ 'csv_process_title' => 'Importação do CSV terminou!',
+ 'csv_process_text' => 'O importador do CSV terminou e processou :rows linhas',
+ 'csv_row' => 'Linha',
+ 'csv_import_with_errors' => 'Houve um erro.|Houve :errors erros.',
+ 'csv_error_see_logs' => 'Verifique o arquivo de log para ver detalhes.',
+ 'csv_process_new_entries' => 'Firefly criou :imported nova(s) transação(ões)',
+ 'csv_start_over' => 'Importar novamente',
+ 'csv_to_index' => 'Voltar para tela inicial',
+ 'csv_upload_not_writeable' => 'Cannot write to the path mentioned here. Cannot upload',
+ 'csv_column__ignore' => '(ignorar esta coluna)',
+ 'csv_column_account-iban' => 'Conta de Ativo (IBAN)',
+ 'csv_column_account-id' => 'ID da Conta de Ativo (correspondente Firefly)',
+ 'csv_column_account-name' => 'Conta de Ativo (nome)',
+ 'csv_column_amount' => 'Valor',
+ 'csv_column_amount-comma-separated' => 'Amount (comma as decimal separator)',
+ 'csv_column_bill-id' => 'ID Fatura (correspondente Firefly)',
+ 'csv_column_bill-name' => 'Nom da Fatura',
+ 'csv_column_budget-id' => 'ID do Orçamento (correspondente Firefly)',
+ 'csv_column_budget-name' => 'Nome do Orçamento',
+ 'csv_column_category-id' => 'ID da Categoria (correspondente Firefly)',
+ 'csv_column_category-name' => 'Nome da Categoria',
+ 'csv_column_currency-code' => 'Código da Moeda (ISO 4217)',
+ 'csv_column_currency-id' => 'ID da Moeda (correspondente Firefly)',
+ 'csv_column_currency-name' => 'Nome da Moeda (correspondente Firefly)',
+ 'csv_column_currency-symbol' => 'SÃmbolo da Moeda (correspondente Firefly)',
+ 'csv_column_date-rent' => 'Rent calculation date',
+ 'csv_column_date-transaction' => 'Data',
+ 'csv_column_description' => 'Descrição',
+ 'csv_column_opposing-iban' => 'Opposing account (IBAN)',
+ 'csv_column_opposing-id' => 'Opposing account ID (matching Firefly)',
+ 'csv_column_opposing-name' => 'Opposing account (name)',
+ 'csv_column_rabo-debet-credit' => 'Rabobank specific debet/credit indicator',
+ 'csv_column_ing-debet-credit' => 'ING specific debet/credit indicator',
+ 'csv_column_sepa-ct-id' => 'SEPA Credit Transfer end-to-end ID',
+ 'csv_column_sepa-ct-op' => 'SEPA Credit Transfer opposing account',
+ 'csv_column_sepa-db' => 'SEPA Direct Debet',
+ 'csv_column_tags-comma' => 'Tags (separadas por vÃrgula)',
+ 'csv_column_tags-space' => 'Tags (separadas por espaço)',
+ 'csv_column_account-number' => 'Asset account (account number)',
+ 'csv_column_opposing-number' => 'Opposing account (account number)',
+ 'csv_specifix_RabobankDescription' => 'Select this when you\'re importing Rabobank CSV export files.',
+ 'csv_specifix_AbnAmroDescription' => 'Select this when you\'re importing ABN AMRO CSV export files.',
+ 'csv_specifix_Dummy' => 'Checking this has no effect whatsoever.',
+ 'csv_import_account_help' => 'If your CSV file does NOT contain information about your asset account(s), use this dropdown to select to which account the transactions in the CSV belong to.',
+ 'csv_delimiter_help' => 'Choose the field delimiter that is used in your input file. If not sure, comma is the safest option.',
+ 'csv_date_parse_error' => 'Could not parse a valid date from ":value", using the format ":format". Are you sure your CSV is correct?',
// create new stuff:
- 'create_new_withdrawal' => 'Criar nova retirada',
- 'create_new_deposit' => 'Criar um novo depósito',
- 'create_new_transfer' => 'Criar nova transferência',
- 'create_new_asset' => 'Criar nova conta de ativo',
- 'create_new_expense' => 'Criar nova conta de despesa',
- 'create_new_revenue' => 'Criar nova conta de receita',
- 'create_new_piggy_bank' => 'Criar novo cofrinho',
- 'create_new_bill' => 'Criar nova fatura',
+ 'create_new_withdrawal' => 'Criar nova retirada',
+ 'create_new_deposit' => 'Criar um novo depósito',
+ 'create_new_transfer' => 'Criar nova transferência',
+ 'create_new_asset' => 'Criar nova conta de ativo',
+ 'create_new_expense' => 'Criar nova conta de despesa',
+ 'create_new_revenue' => 'Criar nova conta de receita',
+ 'create_new_piggy_bank' => 'Criar novo cofrinho',
+ 'create_new_bill' => 'Criar nova fatura',
// currencies:
- 'create_currency' => 'Criar uma nova moeda',
- 'edit_currency' => 'Editar moeda ":name"',
- 'store_currency' => 'Armazenar nova moeda',
- 'update_currency' => 'Atualizar moeda',
- 'new_default_currency' => ':name is now the default currency.',
- 'cannot_delete_currency' => 'Cannot delete :name because there are still transactions attached to it!',
- 'deleted_currency' => 'Currency :name deleted',
- 'created_currency' => 'Currency :name created',
- 'updated_currency' => 'Currency :name updated',
- 'ask_site_owner' => 'Please ask :owner to add, remove or edit currencies.',
- 'currencies_intro' => 'Firefly III supports various currencies which you can set and enable here.',
- 'make_default_currency' => 'make default',
- 'default_currency' => 'default',
+ 'create_currency' => 'Criar uma nova moeda',
+ 'edit_currency' => 'Editar moeda ":name"',
+ 'store_currency' => 'Armazenar nova moeda',
+ 'update_currency' => 'Atualizar moeda',
+ 'new_default_currency' => ':name is now the default currency.',
+ 'cannot_delete_currency' => 'Cannot delete :name because there are still transactions attached to it!',
+ 'deleted_currency' => 'Currency :name deleted',
+ 'created_currency' => 'Currency :name created',
+ 'updated_currency' => 'Currency :name updated',
+ 'ask_site_owner' => 'Please ask :owner to add, remove or edit currencies.',
+ 'currencies_intro' => 'Firefly III supports various currencies which you can set and enable here.',
+ 'make_default_currency' => 'make default',
+ 'default_currency' => 'default',
// new user:
- 'submit' => 'Enviar',
- 'getting_started' => 'Iniciar',
- 'to_get_started' => 'To get started with Firefly, please enter your current bank\'s name, and the balance of your checking account:',
- 'savings_balance_text' => 'If you have a savings account, please enter the current balance of your savings account:',
- 'cc_balance_text' => 'If you have a credit card, please enter your credit card\'s limit.',
+ 'submit' => 'Enviar',
+ 'getting_started' => 'Iniciar',
+ 'to_get_started' => 'To get started with Firefly, please enter your current bank\'s name, and the balance of your checking account:',
+ 'savings_balance_text' => 'If you have a savings account, please enter the current balance of your savings account:',
+ 'cc_balance_text' => 'If you have a credit card, please enter your credit card\'s limit.',
// forms:
- 'mandatoryFields' => 'Campos obrigatórios',
- 'optionalFields' => 'Campos opcionais',
- 'options' => 'Opções',
- 'something' => 'Qualquer coisa!',
+ 'mandatoryFields' => 'Campos obrigatórios',
+ 'optionalFields' => 'Campos opcionais',
+ 'options' => 'Opções',
+ 'something' => 'Qualquer coisa!',
// budgets:
- 'create_new_budget' => 'Criar um novo orçamento',
- 'store_new_budget' => 'Armazenar novo orçamento',
- 'availableIn' => 'DisponÃvel em :date',
- 'transactionsWithoutBudget' => 'Despesas sem orçamentos',
- 'transactionsWithoutBudgetDate' => 'Despesas sem orçamentos em :date',
- 'createBudget' => 'Novo orçamento',
- 'inactiveBudgets' => 'Orçamentos inativos',
- 'without_budget_between' => 'Transactions without a budget between :start and :end',
- 'budget_in_month' => ':name no :month',
- 'delete_budget' => 'Delete budget ":name"',
- 'edit_budget' => 'Edit budget ":name"',
- 'update_amount' => 'Update amount',
- 'update_budget' => 'Update budget',
+ 'create_new_budget' => 'Criar um novo orçamento',
+ 'store_new_budget' => 'Armazenar novo orçamento',
+ 'availableIn' => 'DisponÃvel em :date',
+ 'transactionsWithoutBudget' => 'Despesas sem orçamentos',
+ 'transactionsWithoutBudgetDate' => 'Despesas sem orçamentos em :date',
+ 'createBudget' => 'Novo orçamento',
+ 'inactiveBudgets' => 'Orçamentos inativos',
+ 'without_budget_between' => 'Transactions without a budget between :start and :end',
+ 'budget_in_month' => ':name no :month',
+ 'delete_budget' => 'Delete budget ":name"',
+ 'edit_budget' => 'Edit budget ":name"',
+ 'update_amount' => 'Update amount',
+ 'update_budget' => 'Update budget',
// bills:
- 'delete_bill' => 'Delete bill ":name"',
- 'edit_bill' => 'Edit bill ":name"',
- 'update_bill' => 'Update bill',
- 'store_new_bill' => 'Store new bill',
+ 'delete_bill' => 'Delete bill ":name"',
+ 'edit_bill' => 'Edit bill ":name"',
+ 'update_bill' => 'Update bill',
+ 'store_new_bill' => 'Store new bill',
// accounts:
- 'details_for_asset' => 'Details for asset account ":name"',
- 'details_for_expense' => 'Details for expense account ":name"',
- 'details_for_revenue' => 'Details for revenue account ":name"',
- 'details_for_cash' => 'Details for cash account ":name"',
- 'store_new_asset_account' => 'Store new asset account',
- 'store_new_expense_account' => 'Store new expense account',
- 'store_new_revenue_account' => 'Store new revenue account',
- 'edit_asset_account' => 'Edit asset account ":name"',
- 'edit_expense_account' => 'Edit expense account ":name"',
- 'edit_revenue_account' => 'Edit revenue account ":name"',
- 'delete_asset_account' => 'Delete asset account ":name"',
- 'delete_expense_account' => 'Delete expense account ":name"',
- 'delete_revenue_account' => 'Delete revenue account ":name"',
- 'asset_deleted' => 'Successfully deleted asset account ":name"',
- 'expense_deleted' => 'Successfully deleted expense account ":name"',
- 'revenue_deleted' => 'Successfully deleted revenue account ":name"',
- 'update_asset_account' => 'Update asset account',
- 'update_expense_account' => 'Update expense account',
- 'update_revenue_account' => 'Update revenue account',
- 'make_new_asset_account' => 'Create a new asset account',
- 'make_new_expense_account' => 'Create a new expense account',
- 'make_new_revenue_account' => 'Create a new revenue account',
- 'asset_accounts' => 'Asset accounts',
- 'expense_accounts' => 'Expense accounts',
- 'revenue_accounts' => 'Revenue accounts',
- 'accountExtraHelp_asset' => '',
- 'accountExtraHelp_expense' => '',
- 'accountExtraHelp_revenue' => '',
- 'account_type' => 'Account type',
- 'save_transactions_by_moving' => 'Save these transaction(s) by moving them to another account:',
+ 'details_for_asset' => 'Details for asset account ":name"',
+ 'details_for_expense' => 'Details for expense account ":name"',
+ 'details_for_revenue' => 'Details for revenue account ":name"',
+ 'details_for_cash' => 'Details for cash account ":name"',
+ 'store_new_asset_account' => 'Store new asset account',
+ 'store_new_expense_account' => 'Store new expense account',
+ 'store_new_revenue_account' => 'Store new revenue account',
+ 'edit_asset_account' => 'Edit asset account ":name"',
+ 'edit_expense_account' => 'Edit expense account ":name"',
+ 'edit_revenue_account' => 'Edit revenue account ":name"',
+ 'delete_asset_account' => 'Delete asset account ":name"',
+ 'delete_expense_account' => 'Delete expense account ":name"',
+ 'delete_revenue_account' => 'Delete revenue account ":name"',
+ 'asset_deleted' => 'Successfully deleted asset account ":name"',
+ 'expense_deleted' => 'Successfully deleted expense account ":name"',
+ 'revenue_deleted' => 'Successfully deleted revenue account ":name"',
+ 'update_asset_account' => 'Update asset account',
+ 'update_expense_account' => 'Update expense account',
+ 'update_revenue_account' => 'Update revenue account',
+ 'make_new_asset_account' => 'Create a new asset account',
+ 'make_new_expense_account' => 'Create a new expense account',
+ 'make_new_revenue_account' => 'Create a new revenue account',
+ 'asset_accounts' => 'Asset accounts',
+ 'expense_accounts' => 'Expense accounts',
+ 'revenue_accounts' => 'Revenue accounts',
+ 'accountExtraHelp_asset' => '',
+ 'accountExtraHelp_expense' => '',
+ 'accountExtraHelp_revenue' => '',
+ 'account_type' => 'Account type',
+ 'save_transactions_by_moving' => 'Save these transaction(s) by moving them to another account:',
// categories:
- 'new_category' => 'New category',
- 'create_new_category' => 'Create a new category',
- 'without_category' => 'Without a category',
- 'update_category' => 'Wijzig categorie',
- 'categories' => 'Categories',
- 'edit_category' => 'Edit category ":name"',
- 'no_category' => '(no category)',
- 'category' => 'Category',
- 'delete_category' => 'Delete category ":name"',
- 'store_category' => 'Store new category',
- 'without_category_between' => 'Without category between :start and :end',
+ 'new_category' => 'New category',
+ 'create_new_category' => 'Create a new category',
+ 'without_category' => 'Without a category',
+ 'update_category' => 'Wijzig categorie',
+ 'categories' => 'Categories',
+ 'edit_category' => 'Edit category ":name"',
+ 'no_category' => '(no category)',
+ 'category' => 'Category',
+ 'delete_category' => 'Delete category ":name"',
+ 'store_category' => 'Store new category',
+ 'without_category_between' => 'Without category between :start and :end',
// transactions:
- 'update_withdrawal' => 'Update withdrawal',
- 'update_deposit' => 'Update deposit',
- 'update_transfer' => 'Update transfer',
- 'delete_withdrawal' => 'Delete withdrawal ":description"',
- 'delete_deposit' => 'Delete deposit ":description"',
- 'delete_transfer' => 'Delete transfer ":description"',
+ 'update_withdrawal' => 'Update withdrawal',
+ 'update_deposit' => 'Update deposit',
+ 'update_transfer' => 'Update transfer',
+ 'delete_withdrawal' => 'Delete withdrawal ":description"',
+ 'delete_deposit' => 'Delete deposit ":description"',
+ 'delete_transfer' => 'Delete transfer ":description"',
// new user:
- 'welcome' => 'Welcome to Firefly!',
- 'createNewAsset' => 'Create a new asset account to get started. ' .
- 'This will allow you to create transactions and start your financial management',
- 'createNewAssetButton' => 'Criar nova conta de ativo',
+ 'welcome' => 'Welcome to Firefly!',
+ 'createNewAsset' => 'Create a new asset account to get started. ' .
+ 'This will allow you to create transactions and start your financial management',
+ 'createNewAssetButton' => 'Criar nova conta de ativo',
// home page:
- 'yourAccounts' => 'Your accounts',
- 'budgetsAndSpending' => 'Budgets and spending',
- 'savings' => 'Savings',
- 'markAsSavingsToContinue' => 'Mark your asset accounts as "Savings account" to fill this panel',
- 'createPiggyToContinue' => 'Create piggy banks to fill this panel.',
- 'newWithdrawal' => 'New expense',
- 'newDeposit' => 'Novo depósito',
- 'newTransfer' => 'Nova transferência',
- 'moneyIn' => 'Money in',
- 'moneyOut' => 'Money out',
- 'billsToPay' => 'Bills to pay',
- 'billsPaid' => 'Bills paid',
- 'viewDetails' => 'View details',
- 'divided' => 'divided',
- 'toDivide' => 'left to divide',
+ 'yourAccounts' => 'Your accounts',
+ 'budgetsAndSpending' => 'Budgets and spending',
+ 'savings' => 'Savings',
+ 'markAsSavingsToContinue' => 'Mark your asset accounts as "Savings account" to fill this panel',
+ 'createPiggyToContinue' => 'Create piggy banks to fill this panel.',
+ 'newWithdrawal' => 'New expense',
+ 'newDeposit' => 'Novo depósito',
+ 'newTransfer' => 'Nova transferência',
+ 'moneyIn' => 'Money in',
+ 'moneyOut' => 'Money out',
+ 'billsToPay' => 'Bills to pay',
+ 'billsPaid' => 'Bills paid',
+ 'viewDetails' => 'View details',
+ 'divided' => 'divided',
+ 'toDivide' => 'left to divide',
// menu and titles, should be recycled as often as possible:
- 'toggleNavigation' => 'Toggle navigation',
- 'currency' => 'Currency',
- 'preferences' => 'Preferences',
- 'logout' => 'Logout',
- 'searchPlaceholder' => 'Search...',
- 'dashboard' => 'Dashboard',
- 'currencies' => 'Currencies',
- 'accounts' => 'Accounts',
- 'Asset account' => 'Asset account',
- 'Default account' => 'Asset account',
- 'Expense account' => 'Conta de Despesa',
- 'Revenue account' => 'Conta de Receita',
- 'Initial balance account' => 'Initial balance account',
- 'budgets' => 'Budgets',
- 'tags' => 'Tags',
- 'reports' => 'Relatórios',
- 'transactions' => 'Transações',
- 'expenses' => 'Despesas',
- 'income' => 'Receita / Renda',
- 'transfers' => 'Transferências',
- 'moneyManagement' => 'Gerenciamento de Dinheiro',
- 'piggyBanks' => 'Cofrinhos',
- 'bills' => 'Faturas',
- 'createNew' => 'Criar nova(o)',
- 'withdrawal' => 'Retirada',
- 'deposit' => 'Depósito',
- 'account' => 'Conta',
- 'transfer' => 'Transferência',
- 'Withdrawal' => 'Retirada',
- 'Deposit' => 'Depósito',
- 'Transfer' => 'Transferência',
- 'bill' => 'Fatura',
- 'yes' => 'Sim',
- 'no' => 'Não',
- 'amount' => 'Valor',
- 'newBalance' => 'Novo saldo',
- 'overview' => 'Visão Geral',
- 'saveOnAccount' => 'Salvar na conta',
- 'unknown' => 'Desconhecido',
- 'daily' => 'Diário',
- 'weekly' => 'Semanal',
- 'monthly' => 'Mensal',
- 'quarterly' => 'Trimestral',
- 'half-year' => 'Semestral',
- 'yearly' => 'Anual',
- 'profile' => 'Perfil',
+ 'toggleNavigation' => 'Toggle navigation',
+ 'currency' => 'Currency',
+ 'preferences' => 'Preferences',
+ 'logout' => 'Logout',
+ 'searchPlaceholder' => 'Search...',
+ 'dashboard' => 'Dashboard',
+ 'currencies' => 'Currencies',
+ 'accounts' => 'Accounts',
+ 'Asset account' => 'Asset account',
+ 'Default account' => 'Asset account',
+ 'Expense account' => 'Conta de Despesa',
+ 'Revenue account' => 'Conta de Receita',
+ 'Initial balance account' => 'Initial balance account',
+ 'budgets' => 'Budgets',
+ 'tags' => 'Tags',
+ 'reports' => 'Relatórios',
+ 'transactions' => 'Transações',
+ 'expenses' => 'Despesas',
+ 'income' => 'Receita / Renda',
+ 'transfers' => 'Transferências',
+ 'moneyManagement' => 'Gerenciamento de Dinheiro',
+ 'piggyBanks' => 'Cofrinhos',
+ 'bills' => 'Faturas',
+ 'createNew' => 'Criar nova(o)',
+ 'withdrawal' => 'Retirada',
+ 'deposit' => 'Depósito',
+ 'account' => 'Conta',
+ 'transfer' => 'Transferência',
+ 'Withdrawal' => 'Retirada',
+ 'Deposit' => 'Depósito',
+ 'Transfer' => 'Transferência',
+ 'bill' => 'Fatura',
+ 'yes' => 'Sim',
+ 'no' => 'Não',
+ 'amount' => 'Valor',
+ 'newBalance' => 'Novo saldo',
+ 'overview' => 'Visão Geral',
+ 'saveOnAccount' => 'Salvar na conta',
+ 'unknown' => 'Desconhecido',
+ 'daily' => 'Diário',
+ 'weekly' => 'Semanal',
+ 'monthly' => 'Mensal',
+ 'quarterly' => 'Trimestral',
+ 'half-year' => 'Semestral',
+ 'yearly' => 'Anual',
+ 'profile' => 'Perfil',
// reports:
- 'report_default' => 'Default financial report for :start until :end',
- 'quick_link_reports' => 'Quick links',
- 'quick_link_default_report' => 'Default financial report',
- 'report_this_month_quick' => 'Current month, all accounts',
- 'report_this_year_quick' => 'Current year, all accounts',
- 'report_this_fiscal_year_quick' => 'Current fiscal year, all accounts',
- 'report_all_time_quick' => 'All-time, all accounts',
- 'reports_can_bookmark' => 'Remember that reports can be bookmarked.',
- 'incomeVsExpenses' => 'Renda vs. Despesas',
- 'accountBalances' => 'Saldos de Contas',
- 'balanceStartOfYear' => 'Balance at start of year',
- 'balanceEndOfYear' => 'Balance at end of year',
- 'balanceStartOfMonth' => 'Balance at start of month',
- 'balanceEndOfMonth' => 'Balance at end of month',
- 'balanceStart' => 'Balance at start of period',
- 'balanceEnd' => 'Balance at end of period',
- 'reportsOwnAccounts' => 'Reports for your own accounts',
- 'reportsOwnAccountsAndShared' => 'Reports for your own accounts and shared accounts',
- 'splitByAccount' => 'Split by account',
- 'balancedByTransfersAndTags' => 'Balanced by transfers and tags',
- 'coveredWithTags' => 'Covered with tags',
- 'leftUnbalanced' => 'Left unbalanced',
- 'expectedBalance' => 'Saldo Experado',
- 'outsideOfBudgets' => 'Fora do orçamento',
- 'leftInBudget' => 'Deixou no orçamento',
- 'sumOfSums' => 'Soma dos montantes',
- 'noCategory' => '(no category)',
- 'notCharged' => 'Não cobrado (ainda)',
- 'inactive' => 'Inativo',
- 'difference' => 'Diferente',
- 'in' => 'Entrada',
- 'out' => 'SaÃda',
- 'topX' => 'top :number',
- 'showTheRest' => 'Mostrar tudo',
- 'hideTheRest' => 'Mostrar apenas os top :number',
- 'sum_of_year' => 'Soma do ano',
- 'sum_of_years' => 'Sum of years',
- 'average_of_year' => 'Média do ano',
- 'average_of_years' => 'Average of years',
- 'categories_earned_in_year' => 'Categories (by earnings)',
- 'categories_spent_in_year' => 'Categories (by spendings)',
- 'report_type' => 'Report type',
- 'report_type_default' => 'Default financial report',
- 'report_included_accounts' => 'Included accounts',
- 'report_date_range' => 'Date range',
- 'report_include_help' => 'In all cases, transfers to shared accounts count as expenses, and transfers from shared accounts count as income.',
- 'report_preset_ranges' => 'Pre-set ranges',
- 'shared' => 'Shared',
- 'fiscal_year' => 'Fiscal year',
+ 'report_default' => 'Default financial report for :start until :end',
+ 'report_audit' => 'Transaction history overview for :start until :end',
+ 'quick_link_reports' => 'Quick links',
+ 'quick_link_default_report' => 'Default financial report',
+ 'report_this_month_quick' => 'Current month, all accounts',
+ 'report_this_year_quick' => 'Current year, all accounts',
+ 'report_this_fiscal_year_quick' => 'Current fiscal year, all accounts',
+ 'report_all_time_quick' => 'All-time, all accounts',
+ 'reports_can_bookmark' => 'Remember that reports can be bookmarked.',
+ 'incomeVsExpenses' => 'Renda vs. Despesas',
+ 'accountBalances' => 'Saldos de Contas',
+ 'balanceStartOfYear' => 'Balance at start of year',
+ 'balanceEndOfYear' => 'Balance at end of year',
+ 'balanceStartOfMonth' => 'Balance at start of month',
+ 'balanceEndOfMonth' => 'Balance at end of month',
+ 'balanceStart' => 'Balance at start of period',
+ 'balanceEnd' => 'Balance at end of period',
+ 'reportsOwnAccounts' => 'Reports for your own accounts',
+ 'reportsOwnAccountsAndShared' => 'Reports for your own accounts and shared accounts',
+ 'splitByAccount' => 'Split by account',
+ 'balancedByTransfersAndTags' => 'Balanced by transfers and tags',
+ 'coveredWithTags' => 'Covered with tags',
+ 'leftUnbalanced' => 'Left unbalanced',
+ 'expectedBalance' => 'Saldo Experado',
+ 'outsideOfBudgets' => 'Fora do orçamento',
+ 'leftInBudget' => 'Deixou no orçamento',
+ 'sumOfSums' => 'Soma dos montantes',
+ 'noCategory' => '(no category)',
+ 'notCharged' => 'Não cobrado (ainda)',
+ 'inactive' => 'Inativo',
+ 'difference' => 'Diferente',
+ 'in' => 'Entrada',
+ 'out' => 'SaÃda',
+ 'topX' => 'top :number',
+ 'showTheRest' => 'Mostrar tudo',
+ 'hideTheRest' => 'Mostrar apenas os top :number',
+ 'sum_of_year' => 'Soma do ano',
+ 'sum_of_years' => 'Sum of years',
+ 'average_of_year' => 'Média do ano',
+ 'average_of_years' => 'Average of years',
+ 'categories_earned_in_year' => 'Categories (by earnings)',
+ 'categories_spent_in_year' => 'Categories (by spendings)',
+ 'report_type' => 'Report type',
+ 'report_type_default' => 'Default financial report',
+ 'report_type_audit' => 'Transaction history overview (audit)',
+ 'report_included_accounts' => 'Included accounts',
+ 'report_date_range' => 'Date range',
+ 'report_include_help' => 'In all cases, transfers to shared accounts count as expenses, and transfers from shared accounts count as income.',
+ 'report_preset_ranges' => 'Pre-set ranges',
+ 'shared' => 'Shared',
+ 'fiscal_year' => 'Fiscal year',
// charts:
- 'dayOfMonth' => 'Dia do mês',
- 'month' => 'Mês',
- 'budget' => 'Orçamento',
- 'spent' => 'Gasto',
- 'earned' => 'Ganho',
- 'overspent' => 'Gasto excedido',
- 'left' => 'Left',
- 'noBudget' => '(sem orçamento)',
- 'maxAmount' => 'Valor Máximo',
- 'minAmount' => 'Valor MÃnimo',
- 'billEntry' => 'Current bill entry',
- 'name' => 'Nome',
- 'date' => 'Data',
- 'paid' => 'Pago',
- 'unpaid' => 'Não pago',
- 'day' => 'Dia',
- 'budgeted' => 'Orçado',
- 'period' => 'PerÃodo',
- 'balance' => 'Saldo',
- 'summary' => 'Sumário',
- 'sum' => 'Soma',
- 'average' => 'Média',
- 'balanceFor' => 'Saldo para ":name"',
+ 'dayOfMonth' => 'Dia do mês',
+ 'month' => 'Mês',
+ 'budget' => 'Orçamento',
+ 'spent' => 'Gasto',
+ 'earned' => 'Ganho',
+ 'overspent' => 'Gasto excedido',
+ 'left' => 'Left',
+ 'noBudget' => '(sem orçamento)',
+ 'maxAmount' => 'Valor Máximo',
+ 'minAmount' => 'Valor MÃnimo',
+ 'billEntry' => 'Current bill entry',
+ 'name' => 'Nome',
+ 'date' => 'Data',
+ 'paid' => 'Pago',
+ 'unpaid' => 'Não pago',
+ 'day' => 'Dia',
+ 'budgeted' => 'Orçado',
+ 'period' => 'PerÃodo',
+ 'balance' => 'Saldo',
+ 'summary' => 'Sumário',
+ 'sum' => 'Soma',
+ 'average' => 'Média',
+ 'balanceFor' => 'Saldo para ":name"',
// piggy banks:
- 'piggy_bank' => 'Cofrinho',
- 'new_piggy_bank' => 'Criar novo cofrinho',
- 'store_piggy_bank' => 'Store new piggy bank',
- 'account_status' => 'Account status',
- 'left_for_piggy_banks' => 'Left for piggy banks',
- 'sum_of_piggy_banks' => 'Sum of piggy banks',
- 'saved_so_far' => 'Saved so far',
- 'left_to_save' => 'Left to save',
- 'add_money_to_piggy_title' => 'Add money to piggy bank ":name"',
- 'remove_money_from_piggy_title' => 'Remove money from piggy bank ":name"',
- 'add' => 'Adicionar',
- 'remove' => 'Remover',
- 'max_amount_add' => 'The maximum amount you can add is',
- 'max_amount_remove' => 'The maximum amount you can remove is',
- 'update_piggy_button' => 'Update piggy bank',
- 'update_piggy_title' => 'Update piggy bank ":name"',
- 'details' => 'Detalhes',
- 'events' => 'Eventos',
- 'target_amount' => 'Valor alvo',
- 'start_date' => 'Data de InÃcio',
- 'target_date' => 'Data Alvo',
- 'no_target_date' => 'Nenhum data',
- 'todo' => 'A fazer',
- 'table' => 'Tabela',
- 'piggy_bank_not_exists' => 'Piggy bank no longer exists.',
- 'add_any_amount_to_piggy' => 'Add money to this piggy bank to reach your target of :amount.',
- 'add_set_amount_to_piggy' => 'Add :amount to fill this piggy bank on :date',
- 'delete_piggy_bank' => 'Apagar cofrinho ":name"',
+ 'piggy_bank' => 'Cofrinho',
+ 'new_piggy_bank' => 'Criar novo cofrinho',
+ 'store_piggy_bank' => 'Store new piggy bank',
+ 'account_status' => 'Account status',
+ 'left_for_piggy_banks' => 'Left for piggy banks',
+ 'sum_of_piggy_banks' => 'Sum of piggy banks',
+ 'saved_so_far' => 'Saved so far',
+ 'left_to_save' => 'Left to save',
+ 'add_money_to_piggy_title' => 'Add money to piggy bank ":name"',
+ 'remove_money_from_piggy_title' => 'Remove money from piggy bank ":name"',
+ 'add' => 'Adicionar',
+ 'remove' => 'Remover',
+ 'max_amount_add' => 'The maximum amount you can add is',
+ 'max_amount_remove' => 'The maximum amount you can remove is',
+ 'update_piggy_button' => 'Update piggy bank',
+ 'update_piggy_title' => 'Update piggy bank ":name"',
+ 'details' => 'Detalhes',
+ 'events' => 'Eventos',
+ 'target_amount' => 'Valor alvo',
+ 'start_date' => 'Data de InÃcio',
+ 'target_date' => 'Data Alvo',
+ 'no_target_date' => 'Nenhum data',
+ 'todo' => 'A fazer',
+ 'table' => 'Tabela',
+ 'piggy_bank_not_exists' => 'Piggy bank no longer exists.',
+ 'add_any_amount_to_piggy' => 'Add money to this piggy bank to reach your target of :amount.',
+ 'add_set_amount_to_piggy' => 'Add :amount to fill this piggy bank on :date',
+ 'delete_piggy_bank' => 'Apagar cofrinho ":name"',
// tags
- 'regular_tag' => 'Just a regular tag.',
- 'balancing_act' => 'The tag takes at most two transactions; an expense and a transfer. They\'ll balance each other out.',
- 'advance_payment' => 'The tag accepts one expense and any number of deposits aimed to repay the original expense.',
- 'delete_tag' => 'Apagar tag ":tag"',
- 'new_tag' => 'Fazer nova tag',
- 'edit_tag' => 'Editar tag ":tag"',
- 'no_year' => 'Nenhum ano definido',
- 'no_month' => 'Nenhum mês definido',
- 'tag_title_nothing' => 'Tags padrões',
- 'tag_title_balancingAct' => 'Balancing act tags',
- 'tag_title_advancePayment' => 'Advance payment tags',
- 'tags_introduction' => 'Usually tags are singular words, designed to quickly band items together using things like expensive, bill or for-party. In Firefly III, tags can have more properties such as a date, description and location. This allows you to join transactions together in a more meaningful way. For example, you could make a tag called Christmas dinner with friends and add information about the restaurant. Such tags are "singular", you would only use them for a single occasion, perhaps with multiple transactions.',
- 'tags_group' => 'Tags group transactions together, which makes it possible to store reimbursements (in case you front money for others) and other "balancing acts" where expenses are summed up (the payments on your new TV) or where expenses and deposits are cancelling each other out (buying something with saved money). It\'s all up to you. Using tags the old-fashioned way is of course always possible.',
- 'tags_start' => 'Create a tag to get started or enter tags when creating new transactions.',
+ 'regular_tag' => 'Just a regular tag.',
+ 'balancing_act' => 'The tag takes at most two transactions; an expense and a transfer. They\'ll balance each other out.',
+ 'advance_payment' => 'The tag accepts one expense and any number of deposits aimed to repay the original expense.',
+ 'delete_tag' => 'Apagar tag ":tag"',
+ 'new_tag' => 'Fazer nova tag',
+ 'edit_tag' => 'Editar tag ":tag"',
+ 'no_year' => 'Nenhum ano definido',
+ 'no_month' => 'Nenhum mês definido',
+ 'tag_title_nothing' => 'Tags padrões',
+ 'tag_title_balancingAct' => 'Balancing act tags',
+ 'tag_title_advancePayment' => 'Advance payment tags',
+ 'tags_introduction' => 'Usually tags are singular words, designed to quickly band items together using things like expensive, bill or for-party. In Firefly III, tags can have more properties such as a date, description and location. This allows you to join transactions together in a more meaningful way. For example, you could make a tag called Christmas dinner with friends and add information about the restaurant. Such tags are "singular", you would only use them for a single occasion, perhaps with multiple transactions.',
+ 'tags_group' => 'Tags group transactions together, which makes it possible to store reimbursements (in case you front money for others) and other "balancing acts" where expenses are summed up (the payments on your new TV) or where expenses and deposits are cancelling each other out (buying something with saved money). It\'s all up to you. Using tags the old-fashioned way is of course always possible.',
+ 'tags_start' => 'Create a tag to get started or enter tags when creating new transactions.',
];
diff --git a/resources/lang/pt_BR/form.php b/resources/lang/pt_BR/form.php
old mode 100644
new mode 100755
index 322c358c9c..c12730d20a
--- a/resources/lang/pt_BR/form.php
+++ b/resources/lang/pt_BR/form.php
@@ -1,7 +1,14 @@
'Nome do banco',
'bank_balance' => 'Saldo',
'savings_balance' => 'Salda da Poupança',
@@ -37,6 +44,9 @@ return [
'revenue_account' => 'Conta de Receita',
'amount' => 'Valor',
'date' => 'Data',
+ 'interest_date' => 'Interest date',
+ 'book_date' => 'Book date',
+ 'process_date' => 'Processing date',
'category' => 'Categoria',
'tags' => 'Etiquetas',
'deletePermanently' => 'Apagar permanentemente',
@@ -47,6 +57,7 @@ return [
'symbol' => 'SÃmbolo',
'code' => 'Código',
'iban' => 'IBAN',
+ 'accountNumber' => 'Account number',
'csv' => 'Arquivo CSV',
'has_headers' => 'Cabeçalhos',
'date_format' => 'Formato da Data',
@@ -70,40 +81,44 @@ return [
'size' => 'Tamanho',
'trigger' => 'Trigger',
'stop_processing' => 'Stop processing',
-
- 'csv_comma' => 'A comma (,)',
- 'csv_semicolon' => 'A semicolon (;)',
- 'csv_tab' => 'A tab (invisible)',
-
-
- 'delete_account' => 'Apagar conta ":name"',
- 'delete_bill' => 'Apagar fatura ":name"',
- 'delete_budget' => 'Delete budget ":name"',
- 'delete_category' => 'Delete category ":name"',
- 'delete_currency' => 'Delete currency ":name"',
- 'delete_journal' => 'Delete transaction with description ":description"',
- 'delete_attachment' => 'Apagar anexo ":name"',
- 'delete_rule' => 'Delete rule ":title"',
- 'delete_rule_group' => 'Delete rule group ":title"',
-
- 'attachment_areYouSure' => 'Are you sure you want to delete the attachment named ":name"?',
- 'account_areYouSure' => 'Are you sure you want to delete the account named ":name"?',
- 'bill_areYouSure' => 'Você tem certeza que quer apagar a fatura ":name"?',
- 'rule_areYouSure' => 'Are you sure you want to delete the rule titled ":title"?',
- 'ruleGroup_areYouSure' => 'Are you sure you want to delete the rule group titled ":title"?',
- 'budget_areYouSure' => 'Are you sure you want to delete the budget named ":name"?',
- 'category_areYouSure' => 'Are you sure you want to delete the category named ":name"?',
- 'currency_areYouSure' => 'Are you sure you want to delete the currency named ":name"?',
- 'piggyBank_areYouSure' => 'Are you sure you want to delete the piggy bank named ":name"?',
- 'journal_areYouSure' => 'Are you sure you want to delete the transaction described ":description"?',
- 'tag_areYouSure' => 'Você tem certeza que quer apagar a tag ":tag"?',
-
- 'permDeleteWarning' => 'Deleting stuff from Firely is permanent and cannot be undone.',
- 'also_delete_transactions' => 'The only transaction connected to this account will be deleted as well.|All :count transactions connected to this account will be deleted as well.',
- 'also_delete_rules' => 'The only rule connected to this rule group will be deleted as well.|All :count rules connected to this rule group will be deleted as well.',
- 'also_delete_piggyBanks' => 'The only piggy bank connected to this account will be deleted as well.|All :count piggy bank connected to this account will be deleted as well.',
- 'bill_keep_transactions' => 'The only transaction connected to this bill will not be deleted.|All :count transactions connected to this bill will spared deletion.',
- 'budget_keep_transactions' => 'The only transaction connected to this budget will not be deleted.|All :count transactions connected to this budget will spared deletion.',
- 'category_keep_transactions' => 'The only transaction connected to this category will not be deleted.|All :count transactions connected to this category will spared deletion.',
- 'tag_keep_transactions' => 'The only transaction connected to this tag will not be deleted.|All :count transactions connected to this tag will spared deletion.',
+ 'start_date' => 'Start of range',
+ 'end_date' => 'End of range',
+ 'export_start_range' => 'Start of export range',
+ 'export_end_range' => 'End of export range',
+ 'export_format' => 'File format',
+ 'include_attachments' => 'Include uploaded attachments',
+ 'include_config' => 'Include configuration file',
+ 'include_old_uploads' => 'Include imported data',
+ 'accounts' => 'Export transactions from these accounts',
+ 'csv_comma' => 'A comma (,)',
+ 'csv_semicolon' => 'A semicolon (;)',
+ 'csv_tab' => 'A tab (invisible)',
+ 'delete_account' => 'Apagar conta ":name"',
+ 'delete_bill' => 'Apagar fatura ":name"',
+ 'delete_budget' => 'Delete budget ":name"',
+ 'delete_category' => 'Delete category ":name"',
+ 'delete_currency' => 'Delete currency ":name"',
+ 'delete_journal' => 'Delete transaction with description ":description"',
+ 'delete_attachment' => 'Apagar anexo ":name"',
+ 'delete_rule' => 'Delete rule ":title"',
+ 'delete_rule_group' => 'Delete rule group ":title"',
+ 'attachment_areYouSure' => 'Are you sure you want to delete the attachment named ":name"?',
+ 'account_areYouSure' => 'Are you sure you want to delete the account named ":name"?',
+ 'bill_areYouSure' => 'Você tem certeza que quer apagar a fatura ":name"?',
+ 'rule_areYouSure' => 'Are you sure you want to delete the rule titled ":title"?',
+ 'ruleGroup_areYouSure' => 'Are you sure you want to delete the rule group titled ":title"?',
+ 'budget_areYouSure' => 'Are you sure you want to delete the budget named ":name"?',
+ 'category_areYouSure' => 'Are you sure you want to delete the category named ":name"?',
+ 'currency_areYouSure' => 'Are you sure you want to delete the currency named ":name"?',
+ 'piggyBank_areYouSure' => 'Are you sure you want to delete the piggy bank named ":name"?',
+ 'journal_areYouSure' => 'Are you sure you want to delete the transaction described ":description"?',
+ 'tag_areYouSure' => 'Você tem certeza que quer apagar a tag ":tag"?',
+ 'permDeleteWarning' => 'Deleting stuff from Firely is permanent and cannot be undone.',
+ 'also_delete_transactions' => 'The only transaction connected to this account will be deleted as well.|All :count transactions connected to this account will be deleted as well.',
+ 'also_delete_rules' => 'The only rule connected to this rule group will be deleted as well.|All :count rules connected to this rule group will be deleted as well.',
+ 'also_delete_piggyBanks' => 'The only piggy bank connected to this account will be deleted as well.|All :count piggy bank connected to this account will be deleted as well.',
+ 'bill_keep_transactions' => 'The only transaction connected to this bill will not be deleted.|All :count transactions connected to this bill will spared deletion.',
+ 'budget_keep_transactions' => 'The only transaction connected to this budget will not be deleted.|All :count transactions connected to this budget will spared deletion.',
+ 'category_keep_transactions' => 'The only transaction connected to this category will not be deleted.|All :count transactions connected to this category will spared deletion.',
+ 'tag_keep_transactions' => 'The only transaction connected to this tag will not be deleted.|All :count transactions connected to this tag will spared deletion.',
];
diff --git a/resources/lang/pt_BR/help.php b/resources/lang/pt_BR/help.php
old mode 100644
new mode 100755
index 99e2295f4f..024d615c86
--- a/resources/lang/pt_BR/help.php
+++ b/resources/lang/pt_BR/help.php
@@ -1,25 +1,30 @@
'Bem Vindo ao Firefly III',
- 'main-content-text' => 'Do yourself a favor and follow this short guide to make sure you know your way around.',
- 'sidebar-toggle-title' => 'Sidebar to create stuff',
- 'sidebar-toggle-text' => 'Hidden under the plus icon are all the buttons to create new stuff. Accounts, transactions, everything!',
- 'account-menu-title' => 'All your accounts',
- 'account-menu-text' => 'Here you can find all the accounts you\'ve made.',
- 'budget-menu-title' => 'Budgets',
- 'budget-menu-text' => 'Use this page to organise your finances and limit spending.',
- 'report-menu-title' => 'Relatórios',
- 'report-menu-text' => 'Check this out when you want a solid overview of your fiances.',
- 'transaction-menu-title' => 'Transações',
- 'transaction-menu-text' => 'All transactions you\'ve created can be found here.',
- 'option-menu-title' => 'Opções',
- 'option-menu-text' => 'This is pretty self-explanatory.',
- 'main-content-end-title' => 'Fim!',
- 'main-content-end-text' => 'Remember that every page has a small question mark at the right top. Click it to get help about the page you\'re on.',
-
-
+ 'main-content-title' => 'Bem Vindo ao Firefly III',
+ 'main-content-text' => 'Do yourself a favor and follow this short guide to make sure you know your way around.',
+ 'sidebar-toggle-title' => 'Sidebar to create stuff',
+ 'sidebar-toggle-text' => 'Hidden under the plus icon are all the buttons to create new stuff. Accounts, transactions, everything!',
+ 'account-menu-title' => 'All your accounts',
+ 'account-menu-text' => 'Here you can find all the accounts you\'ve made.',
+ 'budget-menu-title' => 'Budgets',
+ 'budget-menu-text' => 'Use this page to organise your finances and limit spending.',
+ 'report-menu-title' => 'Relatórios',
+ 'report-menu-text' => 'Check this out when you want a solid overview of your fiances.',
+ 'transaction-menu-title' => 'Transações',
+ 'transaction-menu-text' => 'All transactions you\'ve created can be found here.',
+ 'option-menu-title' => 'Opções',
+ 'option-menu-text' => 'This is pretty self-explanatory.',
+ 'main-content-end-title' => 'Fim!',
+ 'main-content-end-text' => 'Remember that every page has a small question mark at the right top. Click it to get help about the page you\'re on.',
'index' => 'index',
'home' => 'home',
'accounts-index' => 'accounts.index',
diff --git a/resources/lang/pt_BR/list.php b/resources/lang/pt_BR/list.php
old mode 100644
new mode 100755
index c8c03f946d..64e2bd4bff
--- a/resources/lang/pt_BR/list.php
+++ b/resources/lang/pt_BR/list.php
@@ -1,6 +1,11 @@
'Nome',
@@ -19,6 +24,9 @@ return [
'description' => 'Descrição',
'amount' => 'Total',
'date' => 'Data',
+ 'interest_date' => 'Interest date',
+ 'book_date' => 'Book date',
+ 'process_date' => 'Processing date',
'from' => 'De',
'to' => 'Até',
'budget' => 'Orçamento',
diff --git a/resources/lang/pt_BR/pagination.php b/resources/lang/pt_BR/pagination.php
old mode 100644
new mode 100755
index 6a32f34ac0..b66406464e
--- a/resources/lang/pt_BR/pagination.php
+++ b/resources/lang/pt_BR/pagination.php
@@ -1,19 +1,13 @@
'« Anterior',
'next' => 'Próximo »',
-
];
diff --git a/resources/lang/pt_BR/passwords.php b/resources/lang/pt_BR/passwords.php
old mode 100644
new mode 100755
index fa70e900ba..8690468e9e
--- a/resources/lang/pt_BR/passwords.php
+++ b/resources/lang/pt_BR/passwords.php
@@ -8,22 +8,10 @@
*/
return [
-
- /*
- |--------------------------------------------------------------------------
- |--------------------------------------------------------------------------
- |
- | The following language lines are the default lines which match reasons
- | that are given by the password broker for a password update attempt
- | has failed, such as for an invalid token or invalid new password.
- |
- */
-
- "password" => "As senhas devem ter pelo menos seis caracteres e devem ser iguais.",
- "user" => "Não podemos encontrar um usuário com esse endereço de e-mail.",
- "token" => "Este token de redefinição de senha é inválido.",
- "sent" => "Nós te enviamos um email com um link para trocar a senha!",
- "reset" => "Sua senha foi redefinida!",
- 'blocked' => 'Boa tentativa.',
-
+ 'password' => 'Passwords must be at least six characters and match the confirmation.',
+ 'user' => 'We can\'t find a user with that e-mail address.',
+ 'token' => 'This password reset token is invalid.',
+ 'sent' => 'We have e-mailed your password reset link!',
+ 'reset' => 'Your password has been reset!',
+ 'blocked' => 'Nice try though.',
];
diff --git a/resources/lang/pt_BR/validation.php b/resources/lang/pt_BR/validation.php
old mode 100644
new mode 100755
index daf771cd96..ec3e6fa80a
--- a/resources/lang/pt_BR/validation.php
+++ b/resources/lang/pt_BR/validation.php
@@ -1,69 +1,79 @@
'Este valor é inválido para o disparo selecionado.',
- 'rule_action_value' => 'Este valor é inválido para a ação selecionada.',
- 'invalid_domain' => 'Devido a restrições de segurança, você não pode registrar deste domÃnio.',
- 'file_already_attached' => 'Arquivo ":name" carregado já está anexado para este objeto.',
- 'file_attached' => 'Arquivo carregado com sucesso ":name".',
- 'file_invalid_mime' => 'Arquivo ":name" é do tipo ":mime" que não é aceito como um novo upload.',
- 'file_too_large' => 'Arquivo ":name" é muito grande.',
- "accepted" => "O campo :attribute deve ser aceito.",
- "active_url" => "O campo :attribute não contém um URL válido.",
- "after" => "O campo :attribute deverá conter uma data posterior a :date.",
- "alpha" => "O campo :attribute deverá conter apenas letras.",
- "alpha_dash" => "O campo :attribute deverá conter apenas letras, números e traços.",
- "alpha_num" => "O campo :attribute deverá conter apenas letras e números .",
- "array" => "O campo :attribute precisa ser um conjunto.",
- "unique_for_user" => "Já existe uma entrada com este :attribute.",
- "before" => "O campo :attribute deverá conter uma data anterior a :date.",
- 'unique_object_for_user' => 'Este nome já está em uso',
- 'unique_account_for_user' => 'Este nome de conta já está em uso',
- "between.numeric" => "O campo :attribute deverá ter um valor entre :min - :max.",
- "between.file" => "O campo :attribute deverá ter um tamanho entre :min - :max kilobytes.",
- "between.string" => "O campo :attribute deverá conter entre :min - :max caracteres.",
- "between.array" => "O campo :attribute precisar ter entre :min - :max itens.",
- "boolean" => "O campo :attribute deverá ter o valor verdadeiro ou falso.",
- "confirmed" => "A confirmação para o campo :attribute não coincide.",
- "date" => "O campo :attribute não contém uma data válida.",
- "date_format" => "A data indicada para o campo :attribute não respeita o formato :format.",
- "different" => "Os campos :attribute e :other deverão conter valores diferentes.",
- "digits" => "O campo :attribute deverá conter :digits dÃgitos.",
- "digits_between" => "O campo :attribute deverá conter entre :min a :max dÃgitos.",
- "email" => "O campo :attribute não contém um endereço de email válido.",
- "filled" => "O campo :attribute é obrigatório.",
- "exists" => "O valor selecionado para o campo :attribute é inválido.",
- "image" => "O campo :attribute deverá conter uma imagem.",
- "in" => "O campo :attribute não contém um valor válido.",
- "integer" => "O campo :attribute deverá conter um número inteiro.",
- "ip" => "O campo :attribute deverá conter um IP válido.",
- 'json' => 'O campo :attribute deverá conter uma string JSON válida.',
- "max.numeric" => "O campo :attribute não deverá conter um valor superior a :max.",
- "max.file" => "O campo :attribute não deverá ter um tamanho superior a :max kilobytes.",
- "max.string" => "O campo :attribute não deverá conter mais de :max caracteres.",
- "max.array" => "O campo :attribute deve ter no máximo :max itens.",
- "mimes" => "O campo :attribute deverá conter um arquivo do tipo: :values.",
- "min.numeric" => "O campo :attribute deverá ter um valor superior ou igual a :min.",
- "min.file" => "O campo :attribute deverá ter no mÃnimo :min kilobytes.",
- "min.string" => "O campo :attribute deverá conter no mÃnimo :min caracteres.",
- "min.array" => "O campo :attribute deve ter no mÃnimo :min itens.",
- "not_in" => "O campo :attribute contém um valor inválido.",
- "numeric" => "O campo :attribute deverá conter um valor numérico.",
- "regex" => "O formato do valor para o campo :attribute é inválido.",
- "required" => "O campo :attribute é obrigatório.",
- "required_if" => "O campo :attribute é obrigatório quando o valor do campo :other é igual a :value.",
- 'required_unless' => 'O campo :attribute é obrigatório a menos que :other esteja presente em :values.',
- "required_with" => "O campo :attribute é obrigatório quando :values está presente.",
- "required_with_all" => "O campo :attribute é obrigatório quando um dos :values está presente.",
- "required_without" => "O campo :attribute é obrigatório quanto :values não está presente.",
- "required_without_all" => "O campo :attribute é obrigatório quando nenhum dos :values está presente.",
- "same" => "Os campos :attribute e :other deverão conter valores iguais.",
- "size.numeric" => "O campo :attribute deverá conter o valor :size.",
- "size.file" => "O campo :attribute deverá ter o tamanho de :size kilobytes.",
- "size.string" => "O campo :attribute deverá conter :size caracteres.",
- "size.array" => "O campo :attribute deve ter :size itens.",
- "unique" => "O valor indicado para o campo :attribute já se encontra utilizado.",
- 'string' => 'O campo :attribute deve ser uma string.',
- "url" => "O formato do URL indicado para o campo :attribute é inválido.",
- "timezone" => "O campo :attribute deverá ter um fuso horário válido.",
+ 'iban' => 'This is not a valid IBAN.',
+ 'unique_account_number_for_user' => 'It looks like this account number is already in use.',
+ 'rule_trigger_value' => 'Este valor é inválido para o disparo selecionado.',
+ 'rule_action_value' => 'Este valor é inválido para a ação selecionada.',
+ 'invalid_domain' => 'Devido a restrições de segurança, você não pode registrar deste domÃnio.',
+ 'file_already_attached' => 'Arquivo ":name" carregado já está anexado para este objeto.',
+ 'file_attached' => 'Arquivo carregado com sucesso ":name".',
+ 'file_invalid_mime' => 'Arquivo ":name" é do tipo ":mime" que não é aceito como um novo upload.',
+ 'file_too_large' => 'Arquivo ":name" é muito grande.',
+ 'accepted' => 'O campo :attribute deve ser aceito.',
+ 'active_url' => 'O campo :attribute não contém um URL válido.',
+ 'after' => 'O campo :attribute deverá conter uma data posterior a :date.',
+ 'alpha' => 'O campo :attribute deverá conter apenas letras.',
+ 'alpha_dash' => 'O campo :attribute deverá conter apenas letras, números e traços.',
+ 'alpha_num' => 'O campo :attribute deverá conter apenas letras e números .',
+ 'array' => 'O campo :attribute precisa ser um conjunto.',
+ 'unique_for_user' => 'Já existe uma entrada com este :attribute.',
+ 'before' => 'O campo :attribute deverá conter uma data anterior a :date.',
+ 'unique_object_for_user' => 'Este nome já está em uso',
+ 'unique_account_for_user' => 'Este nome de conta já está em uso',
+ 'between.numeric' => 'O campo :attribute deverá ter um valor entre :min - :max.',
+ 'between.file' => 'O campo :attribute deverá ter um tamanho entre :min - :max kilobytes.',
+ 'between.string' => 'O campo :attribute deverá conter entre :min - :max caracteres.',
+ 'between.array' => 'O campo :attribute precisar ter entre :min - :max itens.',
+ 'boolean' => 'O campo :attribute deverá ter o valor verdadeiro ou falso.',
+ 'confirmed' => 'A confirmação para o campo :attribute não coincide.',
+ 'date' => 'O campo :attribute não contém uma data válida.',
+ 'date_format' => 'A data indicada para o campo :attribute não respeita o formato :format.',
+ 'different' => 'Os campos :attribute e :other deverão conter valores diferentes.',
+ 'digits' => 'O campo :attribute deverá conter :digits dÃgitos.',
+ 'digits_between' => 'O campo :attribute deverá conter entre :min a :max dÃgitos.',
+ 'email' => 'O campo :attribute não contém um endereço de email válido.',
+ 'filled' => 'O campo :attribute é obrigatório.',
+ 'exists' => 'O valor selecionado para o campo :attribute é inválido.',
+ 'image' => 'O campo :attribute deverá conter uma imagem.',
+ 'in' => 'O campo :attribute não contém um valor válido.',
+ 'integer' => 'O campo :attribute deverá conter um número inteiro.',
+ 'ip' => 'O campo :attribute deverá conter um IP válido.',
+ 'json' => 'O campo :attribute deverá conter uma string JSON válida.',
+ 'max.numeric' => 'O campo :attribute não deverá conter um valor superior a :max.',
+ 'max.file' => 'O campo :attribute não deverá ter um tamanho superior a :max kilobytes.',
+ 'max.string' => 'O campo :attribute não deverá conter mais de :max caracteres.',
+ 'max.array' => 'O campo :attribute deve ter no máximo :max itens.',
+ 'mimes' => 'O campo :attribute deverá conter um arquivo do tipo: :values.',
+ 'min.numeric' => 'O campo :attribute deverá ter um valor superior ou igual a :min.',
+ 'min.file' => 'O campo :attribute deverá ter no mÃnimo :min kilobytes.',
+ 'min.string' => 'O campo :attribute deverá conter no mÃnimo :min caracteres.',
+ 'min.array' => 'O campo :attribute deve ter no mÃnimo :min itens.',
+ 'not_in' => 'O campo :attribute contém um valor inválido.',
+ 'numeric' => 'O campo :attribute deverá conter um valor numérico.',
+ 'regex' => 'O formato do valor para o campo :attribute é inválido.',
+ 'required' => 'O campo :attribute é obrigatório.',
+ 'required_if' => 'O campo :attribute é obrigatório quando o valor do campo :other é igual a :value.',
+ 'required_unless' => 'O campo :attribute é obrigatório a menos que :other esteja presente em :values.',
+ 'required_with' => 'O campo :attribute é obrigatório quando :values está presente.',
+ 'required_with_all' => 'O campo :attribute é obrigatório quando um dos :values está presente.',
+ 'required_without' => 'O campo :attribute é obrigatório quanto :values não está presente.',
+ 'required_without_all' => 'O campo :attribute é obrigatório quando nenhum dos :values está presente.',
+ 'same' => 'Os campos :attribute e :other deverão conter valores iguais.',
+ 'size.numeric' => 'O campo :attribute deverá conter o valor :size.',
+ 'size.file' => 'O campo :attribute deverá ter o tamanho de :size kilobytes.',
+ 'size.string' => 'O campo :attribute deverá conter :size caracteres.',
+ 'size.array' => 'O campo :attribute deve ter :size itens.',
+ 'unique' => 'O valor indicado para o campo :attribute já se encontra utilizado.',
+ 'string' => 'O campo :attribute deve ser uma string.',
+ 'url' => 'O formato do URL indicado para o campo :attribute é inválido.',
+ 'timezone' => 'O campo :attribute deverá ter um fuso horário válido.',
+ '2fa_code' => 'The :attribute field is invalid.',
];
diff --git a/resources/views/accounts/create.twig b/resources/views/accounts/create.twig
index a801fede4a..0541560806 100644
--- a/resources/views/accounts/create.twig
+++ b/resources/views/accounts/create.twig
@@ -22,22 +22,26 @@
Sign in to start your session
diff --git a/resources/views/auth/lost-two-factor.twig b/resources/views/auth/lost-two-factor.twig new file mode 100644 index 0000000000..6d010196b5 --- /dev/null +++ b/resources/views/auth/lost-two-factor.twig @@ -0,0 +1,48 @@ + + + + + ++ {{ 'two_factor_lost_intro'|_ }} +
+{{ trans('firefly.two_factor_welcome', {user: user.email}) }}
+{{ 'two_factor_enter_code'|_ }}
+ + + {{ 'two_factor_forgot'|_ }} +