mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2024-11-22 08:56:39 -06:00
Expand search
This commit is contained in:
parent
ba10aa5ca5
commit
02687dfe53
@ -32,33 +32,20 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
*/
|
||||
trait CollectorProperties
|
||||
{
|
||||
/** @var array The standard fields to select. */
|
||||
private $fields;
|
||||
/** @var bool Will be set to true if query result contains account information. (see function withAccountInformation). */
|
||||
private $hasAccountInfo;
|
||||
/** @var bool Will be true if query result includes bill information. */
|
||||
private $hasBillInformation;
|
||||
/** @var bool Will be true if query result contains budget info. */
|
||||
private $hasBudgetInformation;
|
||||
/** @var bool Will be true if query result contains category info. */
|
||||
private $hasCatInformation;
|
||||
/** @var bool Will be true for attachments */
|
||||
private $hasJoinedAttTables;
|
||||
private array $fields;
|
||||
private bool $hasAccountInfo;
|
||||
private bool $hasBillInformation;
|
||||
private bool $hasBudgetInformation;
|
||||
private bool $hasCatInformation;
|
||||
private bool $hasJoinedAttTables;
|
||||
private bool $hasJoinedMetaTables;
|
||||
/** @var bool Will be true of the query has the tag info tables joined. */
|
||||
private $hasJoinedTagTables;
|
||||
/** @var bool */
|
||||
private $hasNotesInformation;
|
||||
/** @var array */
|
||||
private $integerFields;
|
||||
/** @var int The maximum number of results. */
|
||||
private $limit;
|
||||
/** @var int The page to return. */
|
||||
private $page;
|
||||
/** @var HasMany The query object. */
|
||||
private $query;
|
||||
/** @var int Total number of results. */
|
||||
private $total;
|
||||
/** @var User The user object. */
|
||||
private $user;
|
||||
private bool $hasJoinedTagTables;
|
||||
private bool $hasNotesInformation;
|
||||
private array $integerFields;
|
||||
private ?int $limit;
|
||||
private ?int $page;
|
||||
private HasMany $query;
|
||||
private int $total;
|
||||
private ?User $user;
|
||||
private array $postFilters;
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ use FireflyIII\Models\Tag;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Trait MetaCollection
|
||||
@ -295,6 +296,35 @@ trait MetaCollection
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Without tags
|
||||
*
|
||||
* @param Collection $tags
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setWithoutSpecificTags(Collection $tags): GroupCollectorInterface
|
||||
{
|
||||
$this->withTagInformation();
|
||||
|
||||
// this method adds a "postFilter" to the collector.
|
||||
$list = $tags->pluck('tag')->toArray();
|
||||
$filter = function (int $index, array $object) use ($list): bool {
|
||||
foreach($object['transactions'] as $transaction) {
|
||||
foreach($transaction['tags'] as $tag) {
|
||||
if(in_array($tag['name'], $list)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
$this->postFilters[] = $filter;
|
||||
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
@ -307,7 +337,7 @@ trait MetaCollection
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit results to transactions without a bill..
|
||||
* Limit results to transactions without a bill.
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
|
@ -55,6 +55,11 @@ class GroupCollector implements GroupCollectorInterface
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->postFilters = [];
|
||||
$this->user = null;
|
||||
$this->limit = null;
|
||||
$this->page = null;
|
||||
|
||||
$this->hasAccountInfo = false;
|
||||
$this->hasCatInformation = false;
|
||||
$this->hasBudgetInformation = false;
|
||||
@ -240,7 +245,12 @@ class GroupCollector implements GroupCollectorInterface
|
||||
$result = $this->query->get($this->fields);
|
||||
|
||||
// now to parse this into an array.
|
||||
$collection = $this->parseArray($result);
|
||||
$collection = $this->parseArray($result);
|
||||
|
||||
// filter the array using all available post filters:
|
||||
$collection = $this->postFilterCollection($collection);
|
||||
|
||||
// count it and continue:
|
||||
$this->total = $collection->count();
|
||||
|
||||
// now filter the array according to the page and the limit (if necessary)
|
||||
@ -730,7 +740,7 @@ class GroupCollector implements GroupCollectorInterface
|
||||
|
||||
// also merge attachments:
|
||||
if (array_key_exists('attachment_id', $result)) {
|
||||
$uploaded = 1 === (int)$result['attachment_uploaded'];
|
||||
$uploaded = 1 === (int) $result['attachment_uploaded'];
|
||||
$attachmentId = (int) $augumentedJournal['attachment_id'];
|
||||
if (0 !== $attachmentId && $uploaded) {
|
||||
$result['attachments'][$attachmentId] = [
|
||||
@ -738,6 +748,8 @@ class GroupCollector implements GroupCollectorInterface
|
||||
];
|
||||
}
|
||||
}
|
||||
// unset various fields:
|
||||
unset($result['tag_id'], $result['tag_name'], $result['tag_date'], $result['tag_description'], $result['tag_latitude'], $result['tag_longitude'], $result['tag_zoom_level']);
|
||||
|
||||
return $result;
|
||||
}
|
||||
@ -789,4 +801,27 @@ class GroupCollector implements GroupCollectorInterface
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $collection
|
||||
* @return Collection
|
||||
*/
|
||||
private function postFilterCollection(Collection $collection): Collection
|
||||
{
|
||||
Log::debug('Now in postFilterCollection()');
|
||||
$newCollection = new Collection;
|
||||
foreach ($collection as $i => $item) {
|
||||
Log::debug(sprintf('Now working on item #%d/%d', $i + 1, $collection->count()));
|
||||
foreach ($this->postFilters as $func) {
|
||||
if (false === $func($i, $item)) {
|
||||
// skip other filters, continue to next item.
|
||||
Log::debug('Filter returns false, jump to next item.');
|
||||
continue 2;
|
||||
}
|
||||
Log::debug('Filter returns true');
|
||||
}
|
||||
$newCollection->push($item);
|
||||
}
|
||||
return $newCollection;
|
||||
}
|
||||
}
|
||||
|
@ -419,6 +419,15 @@ interface GroupCollectorInterface
|
||||
*/
|
||||
public function setTags(Collection $tags): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* Only when does not have these tags
|
||||
*
|
||||
* @param Collection $tags
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setWithoutSpecificTags(Collection $tags): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* Limit the search to one specific transaction group.
|
||||
*
|
||||
|
@ -782,4 +782,35 @@ class BillRepository implements BillRepositoryInterface
|
||||
|
||||
return $service->update($bill, $data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function billEndsWith(string $query, int $limit): Collection
|
||||
{
|
||||
$search = $this->user->bills();
|
||||
if ('' !== $query) {
|
||||
$search->where('name', 'LIKE', sprintf('%%%s', $query));
|
||||
}
|
||||
$search->orderBy('name', 'ASC')
|
||||
->where('active', true);
|
||||
|
||||
return $search->take($limit)->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function billStartsWith(string $query, int $limit): Collection
|
||||
{
|
||||
$search = $this->user->bills();
|
||||
if ('' !== $query) {
|
||||
$search->where('name', 'LIKE', sprintf('%s%%', $query));
|
||||
}
|
||||
$search->orderBy('name', 'ASC')
|
||||
->where('active', true);
|
||||
|
||||
return $search->take($limit)->get();
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,22 @@ interface BillRepositoryInterface
|
||||
*/
|
||||
public function correctOrder(): void;
|
||||
|
||||
/**
|
||||
* @param string $query
|
||||
* @param int $limit
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function billEndsWith(string $query, int $limit): Collection;
|
||||
|
||||
/**
|
||||
* @param string $query
|
||||
* @param int $limit
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function billStartsWith(string $query, int $limit): Collection;
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
*
|
||||
|
@ -564,4 +564,34 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function budgetEndsWith(string $query, int $limit): Collection
|
||||
{
|
||||
$search = $this->user->budgets();
|
||||
if ('' !== $query) {
|
||||
$search->where('name', 'LIKE', sprintf('%%%s', $query));
|
||||
}
|
||||
$search->orderBy('order', 'ASC')
|
||||
->orderBy('name', 'ASC')->where('active', true);
|
||||
|
||||
return $search->take($limit)->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function budgetStartsWith(string $query, int $limit): Collection
|
||||
{
|
||||
$search = $this->user->budgets();
|
||||
if ('' !== $query) {
|
||||
$search->where('name', 'LIKE', sprintf('%s%%', $query));
|
||||
}
|
||||
$search->orderBy('order', 'ASC')
|
||||
->orderBy('name', 'ASC')->where('active', true);
|
||||
|
||||
return $search->take($limit)->get();
|
||||
}
|
||||
}
|
||||
|
@ -174,4 +174,21 @@ interface BudgetRepositoryInterface
|
||||
* @return Budget
|
||||
*/
|
||||
public function update(Budget $budget, array $data): Budget;
|
||||
|
||||
/**
|
||||
* @param string $query
|
||||
* @param int $limit
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function budgetEndsWith(string $query, int $limit): Collection;
|
||||
|
||||
/**
|
||||
* @param string $query
|
||||
* @param int $limit
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function budgetStartsWith(string $query, int $limit): Collection;
|
||||
|
||||
}
|
||||
|
@ -420,4 +420,30 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function categoryEndsWith(string $query, int $limit): Collection
|
||||
{
|
||||
$search = $this->user->categories();
|
||||
if ('' !== $query) {
|
||||
$search->where('name', 'LIKE', sprintf('%%%s', $query));
|
||||
}
|
||||
|
||||
return $search->take($limit)->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function categoryStartsWith(string $query, int $limit): Collection
|
||||
{
|
||||
$search = $this->user->categories();
|
||||
if ('' !== $query) {
|
||||
$search->where('name', 'LIKE', sprintf('%s%%', $query));
|
||||
}
|
||||
|
||||
return $search->take($limit)->get();
|
||||
}
|
||||
}
|
||||
|
@ -134,6 +134,22 @@ interface CategoryRepositoryInterface
|
||||
*/
|
||||
public function searchCategory(string $query, int $limit): Collection;
|
||||
|
||||
/**
|
||||
* @param string $query
|
||||
* @param int $limit
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function categoryEndsWith(string $query, int $limit): Collection;
|
||||
|
||||
/**
|
||||
* @param string $query
|
||||
* @param int $limit
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function categoryStartsWith(string $query, int $limit): Collection;
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
*/
|
||||
|
@ -186,7 +186,7 @@ class RuleRepository implements RuleRepositoryInterface
|
||||
if ('user_action' === $trigger->trigger_type) {
|
||||
continue;
|
||||
}
|
||||
$needsContext = config(sprintf('firefly.search.operators.%s.needs_context', $trigger->trigger_type)) ?? true;
|
||||
$needsContext = config(sprintf('search.operators.%s.needs_context', $trigger->trigger_type)) ?? true;
|
||||
if (false === $needsContext) {
|
||||
$params[] = sprintf('%s:true', OperatorQuerySearch::getRootOperator($trigger->trigger_type));
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ class EitherConfigKey
|
||||
// triggers and actions:
|
||||
'firefly.rule-actions',
|
||||
'firefly.context-rule-actions',
|
||||
'firefly.search.operators'
|
||||
'search.operators'
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -156,7 +156,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
$parser = new QueryParser();
|
||||
try {
|
||||
$query1 = $parser->parse($query);
|
||||
} catch (TypeError | LogicException $e) {
|
||||
} catch (TypeError|LogicException $e) {
|
||||
Log::error($e->getMessage());
|
||||
Log::error(sprintf('Could not parse search: "%s".', $query));
|
||||
throw new FireflyException('Invalid search value. See the logs.', 0, $e);
|
||||
@ -233,7 +233,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
$this->collector->setUser($user);
|
||||
$this->collector->withAccountInformation()->withCategoryInformation()->withBudgetInformation();
|
||||
|
||||
$this->setLimit((int)app('preferences')->getForUser($user, 'listPageSize', 50)->data);
|
||||
$this->setLimit((int) app('preferences')->getForUser($user, 'listPageSize', 50)->data);
|
||||
|
||||
}
|
||||
|
||||
@ -253,7 +253,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
case Subquery::class:
|
||||
// loop all notes in subquery:
|
||||
foreach ($searchNode->getNodes() as $subNode) { // @phpstan-ignore-line
|
||||
$this->handleSearchNode($subNode); // let's hope it's not too recursive!
|
||||
$this->handleSearchNode($subNode); // let's hope it's not too recursive!
|
||||
}
|
||||
break;
|
||||
case Word::class:
|
||||
@ -265,7 +265,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
case Emoticon::class:
|
||||
case Emoji::class:
|
||||
case Mention::class:
|
||||
$allWords = (string)$searchNode->getValue();
|
||||
$allWords = (string) $searchNode->getValue();
|
||||
Log::debug(sprintf('Add words "%s" to search string, because Node class is "%s"', $allWords, $class));
|
||||
$this->words[] = $allWords;
|
||||
break;
|
||||
@ -276,11 +276,11 @@ class OperatorQuerySearch implements SearchInterface
|
||||
$operator = strtolower($searchNode->getValue());
|
||||
$value = $searchNode->getNode()->getValue();
|
||||
// must be valid operator:
|
||||
if (in_array($operator, $this->validOperators, true) && $this->updateCollector($operator, (string)$value)) {
|
||||
if (in_array($operator, $this->validOperators, true) && $this->updateCollector($operator, (string) $value)) {
|
||||
$this->operators->push(
|
||||
[
|
||||
'type' => self::getRootOperator($operator),
|
||||
'value' => (string)$value,
|
||||
'value' => (string) $value,
|
||||
]
|
||||
);
|
||||
Log::debug(sprintf('Added operator type "%s"', $operator));
|
||||
@ -289,7 +289,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
Log::debug(sprintf('Added INVALID operator type "%s"', $operator));
|
||||
$this->invalidOperators[] = [
|
||||
'type' => $operator,
|
||||
'value' => (string)$value,
|
||||
'value' => (string) $value,
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -322,6 +322,30 @@ class OperatorQuerySearch implements SearchInterface
|
||||
//
|
||||
// all account related searches:
|
||||
//
|
||||
case 'account_is':
|
||||
$this->searchAccount($value, 3, 4);
|
||||
break;
|
||||
case 'account_contains':
|
||||
$this->searchAccount($value, 3, 3);
|
||||
break;
|
||||
case 'account_ends':
|
||||
$this->searchAccount($value, 3, 2);
|
||||
break;
|
||||
case 'account_starts':
|
||||
$this->searchAccount($value, 3, 1);
|
||||
break;
|
||||
case 'account_nr_is':
|
||||
$this->searchAccountNr($value, 3, 4);
|
||||
break;
|
||||
case 'account_nr_contains':
|
||||
$this->searchAccountNr($value, 3, 3);
|
||||
break;
|
||||
case 'account_nr_ends':
|
||||
$this->searchAccountNr($value, 3, 2);
|
||||
break;
|
||||
case 'account_nr_starts':
|
||||
$this->searchAccountNr($value, 3, 1);
|
||||
break;
|
||||
case 'source_account_starts':
|
||||
$this->searchAccount($value, 1, 1);
|
||||
break;
|
||||
@ -347,7 +371,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
$this->searchAccount($value, 1, 3);
|
||||
break;
|
||||
case 'source_account_id':
|
||||
$account = $this->accountRepository->find((int)$value);
|
||||
$account = $this->accountRepository->find((int) $value);
|
||||
if (null !== $account) {
|
||||
$this->collector->setSourceAccounts(new Collection([$account]));
|
||||
}
|
||||
@ -389,7 +413,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
$this->searchAccount($value, 2, 3);
|
||||
break;
|
||||
case 'destination_account_id':
|
||||
$account = $this->accountRepository->find((int)$value);
|
||||
$account = $this->accountRepository->find((int) $value);
|
||||
if (null !== $account) {
|
||||
$this->collector->setDestinationAccounts(new Collection([$account]));
|
||||
}
|
||||
@ -401,7 +425,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
$parts = explode(',', $value);
|
||||
$collection = new Collection;
|
||||
foreach ($parts as $accountId) {
|
||||
$account = $this->accountRepository->find((int)$accountId);
|
||||
$account = $this->accountRepository->find((int) $accountId);
|
||||
if (null !== $account) {
|
||||
$collection->push($account);
|
||||
}
|
||||
@ -481,6 +505,32 @@ class OperatorQuerySearch implements SearchInterface
|
||||
$this->collector->withCategory();
|
||||
break;
|
||||
case 'category_is':
|
||||
$category = $this->categoryRepository->findByName($value);
|
||||
if (null !== $category) {
|
||||
$this->collector->setCategory($category);
|
||||
break;
|
||||
}
|
||||
$this->collector->findNothing();
|
||||
break;
|
||||
case 'category_ends':
|
||||
$result = $this->categoryRepository->categoryEndsWith($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->setCategories($result);
|
||||
}
|
||||
if (0 === $result->count()) {
|
||||
$this->collector->findNothing();
|
||||
}
|
||||
break;
|
||||
case 'category_starts':
|
||||
$result = $this->categoryRepository->categoryStartsWith($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->setCategories($result);
|
||||
}
|
||||
if (0 === $result->count()) {
|
||||
$this->collector->findNothing();
|
||||
}
|
||||
break;
|
||||
case 'category_contains':
|
||||
$result = $this->categoryRepository->searchCategory($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->setCategories($result);
|
||||
@ -498,7 +548,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
case 'has_any_budget':
|
||||
$this->collector->withBudget();
|
||||
break;
|
||||
case 'budget_is':
|
||||
case 'budget_contains':
|
||||
$result = $this->budgetRepository->searchBudget($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->setBudgets($result);
|
||||
@ -507,6 +557,32 @@ class OperatorQuerySearch implements SearchInterface
|
||||
$this->collector->findNothing();
|
||||
}
|
||||
break;
|
||||
case 'budget_is':
|
||||
$budget = $this->budgetRepository->findByName($value);
|
||||
if (null !== $budget) {
|
||||
$this->collector->setBudget($budget);
|
||||
break;
|
||||
}
|
||||
$this->collector->findNothing();
|
||||
break;
|
||||
case 'budget_ends':
|
||||
$result = $this->budgetRepository->budgetEndsWith($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->setBudgets($result);
|
||||
}
|
||||
if (0 === $result->count()) {
|
||||
$this->collector->findNothing();
|
||||
}
|
||||
break;
|
||||
case 'budget_starts':
|
||||
$result = $this->budgetRepository->budgetStartsWith($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->setBudgets($result);
|
||||
}
|
||||
if (0 === $result->count()) {
|
||||
$this->collector->findNothing();
|
||||
}
|
||||
break;
|
||||
//
|
||||
// bill
|
||||
//
|
||||
@ -516,8 +592,33 @@ class OperatorQuerySearch implements SearchInterface
|
||||
case 'has_any_bill':
|
||||
$this->collector->withBill();
|
||||
break;
|
||||
case 'bill_is':
|
||||
case 'bill_contains':
|
||||
$result = $this->billRepository->searchBill($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->setBills($result);
|
||||
break;
|
||||
}
|
||||
$this->collector->findNothing();
|
||||
break;
|
||||
case 'bill_is':
|
||||
$bill = $this->billRepository->findByName($value);
|
||||
if (null !== $bill) {
|
||||
$this->collector->setBill($bill);
|
||||
break;
|
||||
}
|
||||
$this->collector->findNothing();
|
||||
break;
|
||||
case 'bill_ends':
|
||||
$result = $this->billRepository->billEndsWith($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->setBills($result);
|
||||
}
|
||||
if (0 === $result->count()) {
|
||||
$this->collector->findNothing();
|
||||
}
|
||||
break;
|
||||
case 'bill_starts':
|
||||
$result = $this->billRepository->billStartsWith($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->setBills($result);
|
||||
}
|
||||
@ -545,19 +646,25 @@ class OperatorQuerySearch implements SearchInterface
|
||||
$this->collector->findNothing();
|
||||
}
|
||||
break;
|
||||
case 'tag_is_not':
|
||||
$result = $this->tagRepository->searchTag($value);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->setWithoutSpecificTags($result);
|
||||
}
|
||||
break;
|
||||
//
|
||||
// notes
|
||||
//
|
||||
case 'notes_contain':
|
||||
case 'notes_contains':
|
||||
$this->collector->notesContain($value);
|
||||
break;
|
||||
case 'notes_start':
|
||||
case 'notes_starts':
|
||||
$this->collector->notesStartWith($value);
|
||||
break;
|
||||
case 'notes_end':
|
||||
case 'notes_ends':
|
||||
$this->collector->notesEndWith($value);
|
||||
break;
|
||||
case 'notes_are':
|
||||
case 'notes_is':
|
||||
$this->collector->notesExactly($value);
|
||||
break;
|
||||
case 'no_notes':
|
||||
@ -569,10 +676,10 @@ class OperatorQuerySearch implements SearchInterface
|
||||
//
|
||||
// amount
|
||||
//
|
||||
case 'amount_exactly':
|
||||
case 'amount_is':
|
||||
|
||||
// strip comma's, make dots.
|
||||
$value = str_replace(',', '.', (string)$value);
|
||||
$value = str_replace(',', '.', (string) $value);
|
||||
|
||||
$amount = app('steam')->positive($value);
|
||||
Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
|
||||
@ -580,7 +687,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
case 'amount_less':
|
||||
// strip comma's, make dots.
|
||||
$value = str_replace(',', '.', (string)$value);
|
||||
$value = str_replace(',', '.', (string) $value);
|
||||
|
||||
$amount = app('steam')->positive($value);
|
||||
Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
|
||||
@ -589,7 +696,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
case 'amount_more':
|
||||
Log::debug(sprintf('Now handling operator "%s"', $operator));
|
||||
// strip comma's, make dots.
|
||||
$value = str_replace(',', '.', (string)$value);
|
||||
$value = str_replace(',', '.', (string) $value);
|
||||
$amount = app('steam')->positive($value);
|
||||
Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
|
||||
$this->collector->amountMore($amount);
|
||||
@ -657,7 +764,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
*/
|
||||
public static function getRootOperator(string $operator): string
|
||||
{
|
||||
$config = config(sprintf('firefly.search.operators.%s', $operator));
|
||||
$config = config(sprintf('search.operators.%s', $operator));
|
||||
if (null === $config) {
|
||||
throw new FireflyException(sprintf('No configuration for search operator "%s"', $operator));
|
||||
}
|
||||
@ -672,7 +779,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* searchDirection: 1 = source (default), 2 = destination
|
||||
* searchDirection: 1 = source (default), 2 = destination, 3 = both
|
||||
* stringPosition: 1 = start (default), 2 = end, 3 = contains, 4 = is
|
||||
*
|
||||
* @param string $value
|
||||
@ -693,6 +800,11 @@ class OperatorQuerySearch implements SearchInterface
|
||||
$searchTypes = [AccountType::ASSET, AccountType::MORTGAGE, AccountType::LOAN, AccountType::DEBT, AccountType::EXPENSE];
|
||||
$collectorMethod = 'setDestinationAccounts';
|
||||
}
|
||||
// either account could be:
|
||||
if (3 === $searchDirection) {
|
||||
$searchTypes = [AccountType::ASSET, AccountType::MORTGAGE, AccountType::LOAN, AccountType::DEBT, AccountType::EXPENSE, AccountType::REVENUE];
|
||||
$collectorMethod = 'setAccounts';
|
||||
}
|
||||
// string position (default): starts with:
|
||||
$stringMethod = 'str_starts_with';
|
||||
|
||||
@ -733,7 +845,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* searchDirection: 1 = source (default), 2 = destination
|
||||
* searchDirection: 1 = source (default), 2 = destination, 3 = both
|
||||
* stringPosition: 1 = start (default), 2 = end, 3 = contains, 4 = is
|
||||
*
|
||||
* @param string $value
|
||||
@ -754,6 +866,13 @@ class OperatorQuerySearch implements SearchInterface
|
||||
$searchTypes = [AccountType::ASSET, AccountType::MORTGAGE, AccountType::LOAN, AccountType::DEBT, AccountType::EXPENSE];
|
||||
$collectorMethod = 'setDestinationAccounts';
|
||||
}
|
||||
|
||||
// either account could be:
|
||||
if (3 === $searchDirection) {
|
||||
$searchTypes = [AccountType::ASSET, AccountType::MORTGAGE, AccountType::LOAN, AccountType::DEBT, AccountType::EXPENSE, AccountType::REVENUE];
|
||||
$collectorMethod = 'setAccounts';
|
||||
}
|
||||
|
||||
// string position (default): starts with:
|
||||
$stringMethod = 'str_starts_with';
|
||||
|
||||
@ -782,7 +901,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
$filtered = $accounts->filter(
|
||||
function (Account $account) use ($value, $stringMethod) {
|
||||
// either IBAN or account number!
|
||||
$ibanMatch = $stringMethod(strtolower((string)$account->iban), strtolower((string)$value));
|
||||
$ibanMatch = $stringMethod(strtolower((string) $account->iban), strtolower((string) $value));
|
||||
$accountNrMatch = false;
|
||||
/** @var AccountMeta $meta */
|
||||
foreach ($account->accountMeta as $meta) {
|
||||
|
@ -186,7 +186,7 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
}
|
||||
|
||||
// if needs no context, value is different:
|
||||
$needsContext = config(sprintf('firefly.search.operators.%s.needs_context', $ruleTrigger->trigger_type)) ?? true;
|
||||
$needsContext = config(sprintf('search.operators.%s.needs_context', $ruleTrigger->trigger_type)) ?? true;
|
||||
if (false === $needsContext) {
|
||||
Log::debug(sprintf('SearchRuleEngine:: add a rule trigger: %s:true', $ruleTrigger->trigger_type));
|
||||
$searchArray[$ruleTrigger->trigger_type][] = 'true';
|
||||
@ -310,7 +310,7 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
continue;
|
||||
}
|
||||
$searchArray = [];
|
||||
$needsContext = config(sprintf('firefly.search.operators.%s.needs_context', $ruleTrigger->trigger_type)) ?? true;
|
||||
$needsContext = config(sprintf('search.operators.%s.needs_context', $ruleTrigger->trigger_type)) ?? true;
|
||||
if (false === $needsContext) {
|
||||
Log::debug(sprintf('SearchRuleEngine:: non strict, will search for: %s:true', $ruleTrigger->trigger_type));
|
||||
$searchArray[$ruleTrigger->trigger_type] = 'true';
|
||||
|
20
composer.lock
generated
20
composer.lock
generated
@ -5131,16 +5131,16 @@
|
||||
},
|
||||
{
|
||||
"name": "spatie/ignition",
|
||||
"version": "1.2.4",
|
||||
"version": "1.2.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/spatie/ignition.git",
|
||||
"reference": "ec58c125c15eecaa20180f01ef9667d41a568ba8"
|
||||
"reference": "982f69f3c2e525cef62fa23ada047d745e4bcda9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/spatie/ignition/zipball/ec58c125c15eecaa20180f01ef9667d41a568ba8",
|
||||
"reference": "ec58c125c15eecaa20180f01ef9667d41a568ba8",
|
||||
"url": "https://api.github.com/repos/spatie/ignition/zipball/982f69f3c2e525cef62fa23ada047d745e4bcda9",
|
||||
"reference": "982f69f3c2e525cef62fa23ada047d745e4bcda9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -5197,20 +5197,20 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-11T13:28:02+00:00"
|
||||
"time": "2022-03-19T14:07:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spatie/laravel-ignition",
|
||||
"version": "1.0.10",
|
||||
"version": "1.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/spatie/laravel-ignition.git",
|
||||
"reference": "71df77cad94aae4db904aaef1cc2f06950daed76"
|
||||
"reference": "5b8c360d1f6bcba339a6d593efa02816c06d17c3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/71df77cad94aae4db904aaef1cc2f06950daed76",
|
||||
"reference": "71df77cad94aae4db904aaef1cc2f06950daed76",
|
||||
"url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/5b8c360d1f6bcba339a6d593efa02816c06d17c3",
|
||||
"reference": "5b8c360d1f6bcba339a6d593efa02816c06d17c3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -5284,7 +5284,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-17T11:01:36+00:00"
|
||||
"time": "2022-03-19T17:03:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
|
@ -31,6 +31,7 @@ return [
|
||||
'from_account_ends' => ['alias' => true, 'alias_for' => 'source_account_ends', 'needs_context' => true,],
|
||||
'source_account_starts' => ['alias' => false, 'needs_context' => true,],
|
||||
'from_account_starts' => ['alias' => true, 'alias_for' => 'source_account_starts', 'needs_context' => true,],
|
||||
|
||||
'source_account_nr_is' => ['alias' => false, 'needs_context' => true,],
|
||||
'from_account_nr_is' => ['alias' => true, 'alias_for' => 'source_account_nr_is', 'needs_context' => true,],
|
||||
'source_account_nr_contains' => ['alias' => false, 'needs_context' => true,],
|
||||
@ -39,6 +40,7 @@ return [
|
||||
'from_account_nr_ends' => ['alias' => true, 'alias_for' => 'source_account_nr_ends', 'needs_context' => true,],
|
||||
'source_account_nr_starts' => ['alias' => false, 'needs_context' => true,],
|
||||
'from_account_nr_starts' => ['alias' => true, 'alias_for' => 'source_account_nr_starts', 'needs_context' => true,],
|
||||
|
||||
'destination_account_is' => ['alias' => false, 'needs_context' => true,],
|
||||
'to_account_is' => ['alias' => true, 'alias_for' => 'destination_account_is', 'needs_context' => true,],
|
||||
'destination_account_contains' => ['alias' => false, 'needs_context' => true,],
|
||||
@ -49,6 +51,7 @@ return [
|
||||
'to_account_ends' => ['alias' => true, 'alias_for' => 'destination_account_ends', 'needs_context' => true,],
|
||||
'destination_account_starts' => ['alias' => false, 'needs_context' => true,],
|
||||
'to_account_starts' => ['alias' => true, 'alias_for' => 'destination_account_starts', 'needs_context' => true,],
|
||||
|
||||
'destination_account_nr_is' => ['alias' => false, 'needs_context' => true,],
|
||||
'to_account_nr_is' => ['alias' => true, 'alias_for' => 'destination_account_nr_is', 'needs_context' => true,],
|
||||
'destination_account_nr_contains' => ['alias' => false, 'needs_context' => true,],
|
||||
@ -57,14 +60,17 @@ return [
|
||||
'to_account_nr_ends' => ['alias' => true, 'alias_for' => 'destination_account_nr_ends', 'needs_context' => true,],
|
||||
'destination_account_nr_starts' => ['alias' => false, 'needs_context' => true,],
|
||||
'to_account_nr_starts' => ['alias' => true, 'alias_for' => 'destination_account_nr_starts', 'needs_context' => true,],
|
||||
|
||||
'account_is' => ['alias' => false, 'needs_context' => true,],
|
||||
'account_contains' => ['alias' => false, 'needs_context' => true,],
|
||||
'account_ends' => ['alias' => false, 'needs_context' => true,],
|
||||
'account_starts' => ['alias' => false, 'needs_context' => true,],
|
||||
|
||||
'account_nr_is' => ['alias' => false, 'needs_context' => true,],
|
||||
'account_nr_contains' => ['alias' => false, 'needs_context' => true,],
|
||||
'account_nr_ends' => ['alias' => false, 'needs_context' => true,],
|
||||
'account_nr_starts' => ['alias' => false, 'needs_context' => true,],
|
||||
|
||||
'category_is' => ['alias' => false, 'needs_context' => true,],
|
||||
'category_contains' => ['alias' => false, 'needs_context' => true,],
|
||||
'category' => ['alias' => true, 'alias_for' => 'category_contains', 'needs_context' => true,],
|
||||
@ -80,6 +86,7 @@ return [
|
||||
'bill' => ['alias' => true, 'alias_for' => 'bill_contains', 'needs_context' => true,],
|
||||
'bill_ends' => ['alias' => false, 'needs_context' => true,],
|
||||
'bill_starts' => ['alias' => false, 'needs_context' => true,],
|
||||
// TODO here we are
|
||||
'external_id_is' => ['alias' => false, 'needs_context' => true,],
|
||||
'external_id_contains' => ['alias' => false, 'needs_context' => true,],
|
||||
'external_id' => ['alias' => true, 'alias_for' => 'external_id_contains', 'needs_context' => true,],
|
||||
|
@ -24,333 +24,449 @@ declare(strict_types=1);
|
||||
|
||||
return [
|
||||
// general stuff:
|
||||
'close' => 'Close',
|
||||
'actions' => 'Actions',
|
||||
'edit' => 'Edit',
|
||||
'delete' => 'Delete',
|
||||
'split' => 'Split',
|
||||
'single_split' => 'Split',
|
||||
'clone' => 'Clone',
|
||||
'last_seven_days' => 'Last seven days',
|
||||
'last_thirty_days' => 'Last thirty days',
|
||||
'last_180_days' => 'Last 180 days',
|
||||
'YTD' => 'YTD',
|
||||
'welcome_back' => 'What\'s playing?',
|
||||
'everything' => 'Everything',
|
||||
'today' => 'today',
|
||||
'customRange' => 'Custom range',
|
||||
'date_range' => 'Date range',
|
||||
'apply' => 'Apply',
|
||||
'select_date' => 'Select date..',
|
||||
'cancel' => 'Cancel',
|
||||
'from' => 'From',
|
||||
'to' => 'To',
|
||||
'structure' => 'Structure',
|
||||
'help_translating' => 'This help text is not yet available in your language. <a href="https://crowdin.com/project/firefly-iii-help">Will you help translate?</a>',
|
||||
'showEverything' => 'Show everything',
|
||||
'never' => 'Never',
|
||||
'no_results_for_empty_search' => 'Your search was empty, so nothing was found.',
|
||||
'removed_amount' => 'Removed :amount',
|
||||
'added_amount' => 'Added :amount',
|
||||
'asset_account_role_help' => 'Any extra options resulting from your choice can be set later.',
|
||||
'Opening balance' => 'Opening balance',
|
||||
'create_new_stuff' => 'Create new stuff',
|
||||
'new_withdrawal' => 'New withdrawal',
|
||||
'create_new_transaction' => 'Create a new transaction',
|
||||
'sidebar_frontpage_create' => 'Create',
|
||||
'new_transaction' => 'New transaction',
|
||||
'no_rules_for_bill' => 'This bill has no rules associated to it.',
|
||||
'go_to_asset_accounts' => 'View your asset accounts',
|
||||
'go_to_budgets' => 'Go to your budgets',
|
||||
'go_to_withdrawals' => 'Go to your withdrawals',
|
||||
'clones_journal_x' => 'This transaction is a clone of ":description" (#:id)',
|
||||
'go_to_categories' => 'Go to your categories',
|
||||
'go_to_bills' => 'Go to your bills',
|
||||
'go_to_expense_accounts' => 'See your expense accounts',
|
||||
'go_to_revenue_accounts' => 'See your revenue accounts',
|
||||
'go_to_piggies' => 'Go to your piggy banks',
|
||||
'new_deposit' => 'New deposit',
|
||||
'new_transfer' => 'New transfer',
|
||||
'new_transfers' => 'New transfer',
|
||||
'new_asset_account' => 'New asset account',
|
||||
'new_expense_account' => 'New expense account',
|
||||
'new_revenue_account' => 'New revenue account',
|
||||
'new_liabilities_account' => 'New liability',
|
||||
'new_budget' => 'New budget',
|
||||
'new_bill' => 'New bill',
|
||||
'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_danger' => 'Danger!',
|
||||
'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',
|
||||
'help_for_this_page' => 'Help for this page',
|
||||
'help_for_this_page_body' => 'You can find more information about this page <a href="https://docs.firefly-iii.org/">in the documentation</a>.',
|
||||
'two_factor_welcome' => 'Hello!',
|
||||
'two_factor_enter_code' => 'To continue, please enter your two factor authentication code. Your application can generate it for you.',
|
||||
'two_factor_code_here' => 'Enter code here',
|
||||
'two_factor_title' => 'Two factor authentication',
|
||||
'authenticate' => 'Authenticate',
|
||||
'two_factor_forgot_title' => 'Lost two factor authentication',
|
||||
'two_factor_forgot' => 'I forgot my two-factor thing.',
|
||||
'two_factor_lost_header' => 'Lost your two factor authentication?',
|
||||
'two_factor_lost_intro' => 'If you lost your backup codes as well, you have bad luck. This is not something you can fix from the web interface. You have two choices.',
|
||||
'two_factor_lost_fix_self' => 'If you run your own instance of Firefly III, read <a href="https://docs.firefly-iii.org/faq/other#i-lost-my-two-factor-authentication-codes-and-backup-codes">this entry in the FAQ</a> for instructions.',
|
||||
'two_factor_lost_fix_owner' => 'Otherwise, email the site owner, <a href="mailto::site_owner">:site_owner</a> and ask them to reset your two factor authentication.',
|
||||
'mfa_backup_code' => 'You have used a backup code to login to Firefly III. It can\'t be used again, so cross it from your list.',
|
||||
'pref_two_factor_new_backup_codes' => 'Get new backup codes',
|
||||
'pref_two_factor_backup_code_count' => 'You have :count valid backup code.|You have :count valid backup codes.',
|
||||
'2fa_i_have_them' => 'I stored them!',
|
||||
'warning_much_data' => ':days days of data may take a while to load.',
|
||||
'registered' => 'You have registered successfully!',
|
||||
'Default asset account' => 'Default asset account',
|
||||
'no_budget_pointer' => 'You seem to have no budgets yet. You should create some on the <a href="budgets">budgets</a>-page. Budgets can help you keep track of expenses.',
|
||||
'no_bill_pointer' => 'You seem to have no bills yet. You should create some on the <a href="bills">bills</a>-page. Bills can help you keep track of expenses.',
|
||||
'Savings account' => 'Savings account',
|
||||
'Credit card' => 'Credit card',
|
||||
'source_accounts' => 'Source account|Source accounts',
|
||||
'destination_accounts' => 'Destination account|Destination accounts',
|
||||
'user_id_is' => 'Your user id is <strong>:user</strong>',
|
||||
'field_supports_markdown' => 'This field supports <a href="https://en.support.wordpress.com/markdown-quick-reference/">Markdown</a>.',
|
||||
'need_more_help' => 'If you need more help using Firefly III, please <a href="https://github.com/firefly-iii/firefly-iii/issues">open a ticket on Github</a>.',
|
||||
'reenable_intro_text' => 'You can also re-enable <a href="#" id="reenableGuidance">the introduction guidance</a>.',
|
||||
'intro_boxes_after_refresh' => 'The introduction boxes will reappear when you refresh the page.',
|
||||
'show_all_no_filter' => 'Show all transactions without grouping them by date.',
|
||||
'expenses_by_category' => 'Expenses by category',
|
||||
'expenses_by_budget' => 'Expenses by budget',
|
||||
'income_by_category' => 'Income by category',
|
||||
'expenses_by_asset_account' => 'Expenses by asset account',
|
||||
'expenses_by_expense_account' => 'Expenses by expense account',
|
||||
'cannot_redirect_to_account' => 'Firefly III cannot redirect you to the correct page. Apologies.',
|
||||
'sum_of_expenses' => 'Sum of expenses',
|
||||
'sum_of_income' => 'Sum of income',
|
||||
'liabilities' => 'Liabilities',
|
||||
'spent_in_specific_budget' => 'Spent in budget ":budget"',
|
||||
'spent_in_specific_double' => 'Spent in account ":account"',
|
||||
'earned_in_specific_double' => 'Earned in account ":account"',
|
||||
'source_account' => 'Source account',
|
||||
'source_account_reconciliation' => 'You can\'t edit the source account of a reconciliation transaction.',
|
||||
'destination_account' => 'Destination account',
|
||||
'destination_account_reconciliation' => 'You can\'t edit the destination account of a reconciliation transaction.',
|
||||
'sum_of_expenses_in_budget' => 'Spent total in budget ":budget"',
|
||||
'left_in_budget_limit' => 'Left to spend according to budgeting',
|
||||
'current_period' => 'Current period',
|
||||
'show_the_current_period_and_overview' => 'Show the current period and overview',
|
||||
'pref_languages_locale' => 'For a language other than English to work properly, your operating system must be equipped with the correct locale-information. If these are not present, currency data, dates and amounts may be formatted wrong.',
|
||||
'budget_in_period' => 'All transactions for budget ":name" between :start and :end in :currency',
|
||||
'chart_budget_in_period' => 'Chart for all transactions for budget ":name" between :start and :end in :currency',
|
||||
'chart_budget_in_period_only_currency' => 'The amount you budgeted was in :currency, so this chart will only show transactions in :currency.',
|
||||
'chart_account_in_period' => 'Chart for all transactions for account ":name" (:balance) between :start and :end',
|
||||
'chart_category_in_period' => 'Chart for all transactions for category ":name" between :start and :end',
|
||||
'chart_category_all' => 'Chart for all transactions for category ":name"',
|
||||
'clone_withdrawal' => 'Clone this withdrawal',
|
||||
'clone_deposit' => 'Clone this deposit',
|
||||
'clone_transfer' => 'Clone this transfer',
|
||||
'multi_select_no_selection' => 'None selected',
|
||||
'multi_select_select_all' => 'Select all',
|
||||
'multi_select_n_selected' => 'selected',
|
||||
'multi_select_all_selected' => 'All selected',
|
||||
'multi_select_filter_placeholder' => 'Find..',
|
||||
'intro_next_label' => 'Next',
|
||||
'intro_prev_label' => 'Previous',
|
||||
'intro_skip_label' => 'Skip',
|
||||
'intro_done_label' => 'Done',
|
||||
'between_dates_breadcrumb' => 'Between :start and :end',
|
||||
'all_journals_without_budget' => 'All transactions without a budget',
|
||||
'journals_without_budget' => 'Transactions without a budget',
|
||||
'all_journals_without_category' => 'All transactions without a category',
|
||||
'journals_without_category' => 'Transactions without a category',
|
||||
'all_journals_for_account' => 'All transactions for account :name',
|
||||
'chart_all_journals_for_account' => 'Chart of all transactions for account :name',
|
||||
'journals_in_period_for_account' => 'All transactions for account :name between :start and :end',
|
||||
'journals_in_period_for_account_js' => 'All transactions for account {title} between {start} and {end}',
|
||||
'transferred' => 'Transferred',
|
||||
'all_withdrawal' => 'All expenses',
|
||||
'all_transactions' => 'All transactions',
|
||||
'title_withdrawal_between' => 'All expenses between :start and :end',
|
||||
'all_deposit' => 'All revenue',
|
||||
'title_deposit_between' => 'All revenue between :start and :end',
|
||||
'all_transfers' => 'All transfers',
|
||||
'title_transfers_between' => 'All transfers between :start and :end',
|
||||
'all_transfer' => 'All transfers',
|
||||
'all_journals_for_tag' => 'All transactions for tag ":tag"',
|
||||
'title_transfer_between' => 'All transfers between :start and :end',
|
||||
'all_journals_for_category' => 'All transactions for category :name',
|
||||
'all_journals_for_budget' => 'All transactions for budget :name',
|
||||
'chart_all_journals_for_budget' => 'Chart of all transactions for budget :name',
|
||||
'journals_in_period_for_category' => 'All transactions for category :name between :start and :end',
|
||||
'journals_in_period_for_tag' => 'All transactions for tag :tag between :start and :end',
|
||||
'not_available_demo_user' => 'The feature you try to access is not available to demo users.',
|
||||
'exchange_rate_instructions' => 'Asset account "@name" only accepts transactions in @native_currency. If you wish to use @foreign_currency instead, make sure that the amount in @native_currency is known as well:',
|
||||
'transfer_exchange_rate_instructions' => 'Source asset account "@source_name" only accepts transactions in @source_currency. Destination asset account "@dest_name" only accepts transactions in @dest_currency. You must provide the transferred amount correctly in both currencies.',
|
||||
'transaction_data' => 'Transaction data',
|
||||
'invalid_server_configuration' => 'Invalid server configuration',
|
||||
'invalid_locale_settings' => 'Firefly III is unable to format monetary amounts because your server is missing the required packages. There are <a href="https://docs.firefly-iii.org/firefly-iii/advanced-installation/locales/">instructions how to do this</a>.',
|
||||
'quickswitch' => 'Quickswitch',
|
||||
'sign_in_to_start' => 'Sign in to start your session',
|
||||
'sign_in' => 'Sign in',
|
||||
'register_new_account' => 'Register a new account',
|
||||
'forgot_my_password' => 'I forgot my password',
|
||||
'problems_with_input' => 'There were some problems with your input.',
|
||||
'reset_password' => 'Reset your password',
|
||||
'button_reset_password' => 'Reset password',
|
||||
'reset_button' => 'Reset',
|
||||
'want_to_login' => 'I want to login',
|
||||
'login_page_title' => 'Login to Firefly III',
|
||||
'register_page_title' => 'Register at Firefly III',
|
||||
'forgot_pw_page_title' => 'Forgot your password for Firefly III',
|
||||
'reset_pw_page_title' => 'Reset your password for Firefly III',
|
||||
'cannot_reset_demo_user' => 'You cannot reset the password of the demo user.',
|
||||
'no_att_demo_user' => 'The demo user can\'t upload attachments.',
|
||||
'button_register' => 'Register',
|
||||
'authorization' => 'Authorization',
|
||||
'active_bills_only' => 'active bills only',
|
||||
'active_bills_only_total' => 'all active bills',
|
||||
'active_exp_bills_only' => 'active and expected bills only',
|
||||
'active_exp_bills_only_total' => 'all active expected bills only',
|
||||
'per_period_sum_1D' => 'Expected daily costs',
|
||||
'per_period_sum_1W' => 'Expected weekly costs',
|
||||
'per_period_sum_1M' => 'Expected monthly costs',
|
||||
'per_period_sum_3M' => 'Expected quarterly costs',
|
||||
'per_period_sum_6M' => 'Expected half-yearly costs',
|
||||
'per_period_sum_1Y' => 'Expected yearly costs',
|
||||
'average_per_bill' => 'average per bill',
|
||||
'expected_total' => 'expected total',
|
||||
'reconciliation_account_name' => ':name reconciliation (:currency)',
|
||||
'saved' => 'Saved',
|
||||
'advanced_options' => 'Advanced options',
|
||||
'advanced_options_explain' => 'Some pages in Firefly III have advanced options hidden behind this button. This page doesn\'t have anything fancy here, but do check out the others!',
|
||||
'here_be_dragons' => 'Hic sunt dracones',
|
||||
'close' => 'Close',
|
||||
'actions' => 'Actions',
|
||||
'edit' => 'Edit',
|
||||
'delete' => 'Delete',
|
||||
'split' => 'Split',
|
||||
'single_split' => 'Split',
|
||||
'clone' => 'Clone',
|
||||
'last_seven_days' => 'Last seven days',
|
||||
'last_thirty_days' => 'Last thirty days',
|
||||
'last_180_days' => 'Last 180 days',
|
||||
'YTD' => 'YTD',
|
||||
'welcome_back' => 'What\'s playing?',
|
||||
'everything' => 'Everything',
|
||||
'today' => 'today',
|
||||
'customRange' => 'Custom range',
|
||||
'date_range' => 'Date range',
|
||||
'apply' => 'Apply',
|
||||
'select_date' => 'Select date..',
|
||||
'cancel' => 'Cancel',
|
||||
'from' => 'From',
|
||||
'to' => 'To',
|
||||
'structure' => 'Structure',
|
||||
'help_translating' => 'This help text is not yet available in your language. <a href="https://crowdin.com/project/firefly-iii-help">Will you help translate?</a>',
|
||||
'showEverything' => 'Show everything',
|
||||
'never' => 'Never',
|
||||
'no_results_for_empty_search' => 'Your search was empty, so nothing was found.',
|
||||
'removed_amount' => 'Removed :amount',
|
||||
'added_amount' => 'Added :amount',
|
||||
'asset_account_role_help' => 'Any extra options resulting from your choice can be set later.',
|
||||
'Opening balance' => 'Opening balance',
|
||||
'create_new_stuff' => 'Create new stuff',
|
||||
'new_withdrawal' => 'New withdrawal',
|
||||
'create_new_transaction' => 'Create a new transaction',
|
||||
'sidebar_frontpage_create' => 'Create',
|
||||
'new_transaction' => 'New transaction',
|
||||
'no_rules_for_bill' => 'This bill has no rules associated to it.',
|
||||
'go_to_asset_accounts' => 'View your asset accounts',
|
||||
'go_to_budgets' => 'Go to your budgets',
|
||||
'go_to_withdrawals' => 'Go to your withdrawals',
|
||||
'clones_journal_x' => 'This transaction is a clone of ":description" (#:id)',
|
||||
'go_to_categories' => 'Go to your categories',
|
||||
'go_to_bills' => 'Go to your bills',
|
||||
'go_to_expense_accounts' => 'See your expense accounts',
|
||||
'go_to_revenue_accounts' => 'See your revenue accounts',
|
||||
'go_to_piggies' => 'Go to your piggy banks',
|
||||
'new_deposit' => 'New deposit',
|
||||
'new_transfer' => 'New transfer',
|
||||
'new_transfers' => 'New transfer',
|
||||
'new_asset_account' => 'New asset account',
|
||||
'new_expense_account' => 'New expense account',
|
||||
'new_revenue_account' => 'New revenue account',
|
||||
'new_liabilities_account' => 'New liability',
|
||||
'new_budget' => 'New budget',
|
||||
'new_bill' => 'New bill',
|
||||
'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_danger' => 'Danger!',
|
||||
'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',
|
||||
'help_for_this_page' => 'Help for this page',
|
||||
'help_for_this_page_body' => 'You can find more information about this page <a href="https://docs.firefly-iii.org/">in the documentation</a>.',
|
||||
'two_factor_welcome' => 'Hello!',
|
||||
'two_factor_enter_code' => 'To continue, please enter your two factor authentication code. Your application can generate it for you.',
|
||||
'two_factor_code_here' => 'Enter code here',
|
||||
'two_factor_title' => 'Two factor authentication',
|
||||
'authenticate' => 'Authenticate',
|
||||
'two_factor_forgot_title' => 'Lost two factor authentication',
|
||||
'two_factor_forgot' => 'I forgot my two-factor thing.',
|
||||
'two_factor_lost_header' => 'Lost your two factor authentication?',
|
||||
'two_factor_lost_intro' => 'If you lost your backup codes as well, you have bad luck. This is not something you can fix from the web interface. You have two choices.',
|
||||
'two_factor_lost_fix_self' => 'If you run your own instance of Firefly III, read <a href="https://docs.firefly-iii.org/faq/other#i-lost-my-two-factor-authentication-codes-and-backup-codes">this entry in the FAQ</a> for instructions.',
|
||||
'two_factor_lost_fix_owner' => 'Otherwise, email the site owner, <a href="mailto::site_owner">:site_owner</a> and ask them to reset your two factor authentication.',
|
||||
'mfa_backup_code' => 'You have used a backup code to login to Firefly III. It can\'t be used again, so cross it from your list.',
|
||||
'pref_two_factor_new_backup_codes' => 'Get new backup codes',
|
||||
'pref_two_factor_backup_code_count' => 'You have :count valid backup code.|You have :count valid backup codes.',
|
||||
'2fa_i_have_them' => 'I stored them!',
|
||||
'warning_much_data' => ':days days of data may take a while to load.',
|
||||
'registered' => 'You have registered successfully!',
|
||||
'Default asset account' => 'Default asset account',
|
||||
'no_budget_pointer' => 'You seem to have no budgets yet. You should create some on the <a href="budgets">budgets</a>-page. Budgets can help you keep track of expenses.',
|
||||
'no_bill_pointer' => 'You seem to have no bills yet. You should create some on the <a href="bills">bills</a>-page. Bills can help you keep track of expenses.',
|
||||
'Savings account' => 'Savings account',
|
||||
'Credit card' => 'Credit card',
|
||||
'source_accounts' => 'Source account|Source accounts',
|
||||
'destination_accounts' => 'Destination account|Destination accounts',
|
||||
'user_id_is' => 'Your user id is <strong>:user</strong>',
|
||||
'field_supports_markdown' => 'This field supports <a href="https://en.support.wordpress.com/markdown-quick-reference/">Markdown</a>.',
|
||||
'need_more_help' => 'If you need more help using Firefly III, please <a href="https://github.com/firefly-iii/firefly-iii/issues">open a ticket on Github</a>.',
|
||||
'reenable_intro_text' => 'You can also re-enable <a href="#" id="reenableGuidance">the introduction guidance</a>.',
|
||||
'intro_boxes_after_refresh' => 'The introduction boxes will reappear when you refresh the page.',
|
||||
'show_all_no_filter' => 'Show all transactions without grouping them by date.',
|
||||
'expenses_by_category' => 'Expenses by category',
|
||||
'expenses_by_budget' => 'Expenses by budget',
|
||||
'income_by_category' => 'Income by category',
|
||||
'expenses_by_asset_account' => 'Expenses by asset account',
|
||||
'expenses_by_expense_account' => 'Expenses by expense account',
|
||||
'cannot_redirect_to_account' => 'Firefly III cannot redirect you to the correct page. Apologies.',
|
||||
'sum_of_expenses' => 'Sum of expenses',
|
||||
'sum_of_income' => 'Sum of income',
|
||||
'liabilities' => 'Liabilities',
|
||||
'spent_in_specific_budget' => 'Spent in budget ":budget"',
|
||||
'spent_in_specific_double' => 'Spent in account ":account"',
|
||||
'earned_in_specific_double' => 'Earned in account ":account"',
|
||||
'source_account' => 'Source account',
|
||||
'source_account_reconciliation' => 'You can\'t edit the source account of a reconciliation transaction.',
|
||||
'destination_account' => 'Destination account',
|
||||
'destination_account_reconciliation' => 'You can\'t edit the destination account of a reconciliation transaction.',
|
||||
'sum_of_expenses_in_budget' => 'Spent total in budget ":budget"',
|
||||
'left_in_budget_limit' => 'Left to spend according to budgeting',
|
||||
'current_period' => 'Current period',
|
||||
'show_the_current_period_and_overview' => 'Show the current period and overview',
|
||||
'pref_languages_locale' => 'For a language other than English to work properly, your operating system must be equipped with the correct locale-information. If these are not present, currency data, dates and amounts may be formatted wrong.',
|
||||
'budget_in_period' => 'All transactions for budget ":name" between :start and :end in :currency',
|
||||
'chart_budget_in_period' => 'Chart for all transactions for budget ":name" between :start and :end in :currency',
|
||||
'chart_budget_in_period_only_currency' => 'The amount you budgeted was in :currency, so this chart will only show transactions in :currency.',
|
||||
'chart_account_in_period' => 'Chart for all transactions for account ":name" (:balance) between :start and :end',
|
||||
'chart_category_in_period' => 'Chart for all transactions for category ":name" between :start and :end',
|
||||
'chart_category_all' => 'Chart for all transactions for category ":name"',
|
||||
'clone_withdrawal' => 'Clone this withdrawal',
|
||||
'clone_deposit' => 'Clone this deposit',
|
||||
'clone_transfer' => 'Clone this transfer',
|
||||
'multi_select_no_selection' => 'None selected',
|
||||
'multi_select_select_all' => 'Select all',
|
||||
'multi_select_n_selected' => 'selected',
|
||||
'multi_select_all_selected' => 'All selected',
|
||||
'multi_select_filter_placeholder' => 'Find..',
|
||||
'intro_next_label' => 'Next',
|
||||
'intro_prev_label' => 'Previous',
|
||||
'intro_skip_label' => 'Skip',
|
||||
'intro_done_label' => 'Done',
|
||||
'between_dates_breadcrumb' => 'Between :start and :end',
|
||||
'all_journals_without_budget' => 'All transactions without a budget',
|
||||
'journals_without_budget' => 'Transactions without a budget',
|
||||
'all_journals_without_category' => 'All transactions without a category',
|
||||
'journals_without_category' => 'Transactions without a category',
|
||||
'all_journals_for_account' => 'All transactions for account :name',
|
||||
'chart_all_journals_for_account' => 'Chart of all transactions for account :name',
|
||||
'journals_in_period_for_account' => 'All transactions for account :name between :start and :end',
|
||||
'journals_in_period_for_account_js' => 'All transactions for account {title} between {start} and {end}',
|
||||
'transferred' => 'Transferred',
|
||||
'all_withdrawal' => 'All expenses',
|
||||
'all_transactions' => 'All transactions',
|
||||
'title_withdrawal_between' => 'All expenses between :start and :end',
|
||||
'all_deposit' => 'All revenue',
|
||||
'title_deposit_between' => 'All revenue between :start and :end',
|
||||
'all_transfers' => 'All transfers',
|
||||
'title_transfers_between' => 'All transfers between :start and :end',
|
||||
'all_transfer' => 'All transfers',
|
||||
'all_journals_for_tag' => 'All transactions for tag ":tag"',
|
||||
'title_transfer_between' => 'All transfers between :start and :end',
|
||||
'all_journals_for_category' => 'All transactions for category :name',
|
||||
'all_journals_for_budget' => 'All transactions for budget :name',
|
||||
'chart_all_journals_for_budget' => 'Chart of all transactions for budget :name',
|
||||
'journals_in_period_for_category' => 'All transactions for category :name between :start and :end',
|
||||
'journals_in_period_for_tag' => 'All transactions for tag :tag between :start and :end',
|
||||
'not_available_demo_user' => 'The feature you try to access is not available to demo users.',
|
||||
'exchange_rate_instructions' => 'Asset account "@name" only accepts transactions in @native_currency. If you wish to use @foreign_currency instead, make sure that the amount in @native_currency is known as well:',
|
||||
'transfer_exchange_rate_instructions' => 'Source asset account "@source_name" only accepts transactions in @source_currency. Destination asset account "@dest_name" only accepts transactions in @dest_currency. You must provide the transferred amount correctly in both currencies.',
|
||||
'transaction_data' => 'Transaction data',
|
||||
'invalid_server_configuration' => 'Invalid server configuration',
|
||||
'invalid_locale_settings' => 'Firefly III is unable to format monetary amounts because your server is missing the required packages. There are <a href="https://docs.firefly-iii.org/firefly-iii/advanced-installation/locales/">instructions how to do this</a>.',
|
||||
'quickswitch' => 'Quickswitch',
|
||||
'sign_in_to_start' => 'Sign in to start your session',
|
||||
'sign_in' => 'Sign in',
|
||||
'register_new_account' => 'Register a new account',
|
||||
'forgot_my_password' => 'I forgot my password',
|
||||
'problems_with_input' => 'There were some problems with your input.',
|
||||
'reset_password' => 'Reset your password',
|
||||
'button_reset_password' => 'Reset password',
|
||||
'reset_button' => 'Reset',
|
||||
'want_to_login' => 'I want to login',
|
||||
'login_page_title' => 'Login to Firefly III',
|
||||
'register_page_title' => 'Register at Firefly III',
|
||||
'forgot_pw_page_title' => 'Forgot your password for Firefly III',
|
||||
'reset_pw_page_title' => 'Reset your password for Firefly III',
|
||||
'cannot_reset_demo_user' => 'You cannot reset the password of the demo user.',
|
||||
'no_att_demo_user' => 'The demo user can\'t upload attachments.',
|
||||
'button_register' => 'Register',
|
||||
'authorization' => 'Authorization',
|
||||
'active_bills_only' => 'active bills only',
|
||||
'active_bills_only_total' => 'all active bills',
|
||||
'active_exp_bills_only' => 'active and expected bills only',
|
||||
'active_exp_bills_only_total' => 'all active expected bills only',
|
||||
'per_period_sum_1D' => 'Expected daily costs',
|
||||
'per_period_sum_1W' => 'Expected weekly costs',
|
||||
'per_period_sum_1M' => 'Expected monthly costs',
|
||||
'per_period_sum_3M' => 'Expected quarterly costs',
|
||||
'per_period_sum_6M' => 'Expected half-yearly costs',
|
||||
'per_period_sum_1Y' => 'Expected yearly costs',
|
||||
'average_per_bill' => 'average per bill',
|
||||
'expected_total' => 'expected total',
|
||||
'reconciliation_account_name' => ':name reconciliation (:currency)',
|
||||
'saved' => 'Saved',
|
||||
'advanced_options' => 'Advanced options',
|
||||
'advanced_options_explain' => 'Some pages in Firefly III have advanced options hidden behind this button. This page doesn\'t have anything fancy here, but do check out the others!',
|
||||
'here_be_dragons' => 'Hic sunt dracones',
|
||||
|
||||
// Webhooks
|
||||
'webhooks' => 'Webhooks',
|
||||
'webhooks' => 'Webhooks',
|
||||
|
||||
// API access
|
||||
'authorization_request' => 'Firefly III v:version Authorization Request',
|
||||
'authorization_request_intro' => 'Application "<strong>:client</strong>" is requesting permission to access your financial administration. Would you like to authorize <strong>:client</strong> to access these records?',
|
||||
'authorization_request_site' => 'You will be redirected to <code>:url</code> which will then be able to access your Firefly III data.',
|
||||
'authorization_request_invalid' => 'This access request is invalid. Please never follow this link again.',
|
||||
'scopes_will_be_able' => 'This application will be able to:',
|
||||
'button_authorize' => 'Authorize',
|
||||
'none_in_select_list' => '(none)',
|
||||
'no_piggy_bank' => '(no piggy bank)',
|
||||
'name_in_currency' => ':name in :currency',
|
||||
'paid_in_currency' => 'Paid in :currency',
|
||||
'unpaid_in_currency' => 'Unpaid in :currency',
|
||||
'is_alpha_warning' => 'You are running an ALPHA version. Be wary of bugs and issues.',
|
||||
'is_beta_warning' => 'You are running an BETA version. Be wary of bugs and issues.',
|
||||
'all_destination_accounts' => 'Destination accounts',
|
||||
'all_source_accounts' => 'Source accounts',
|
||||
'back_to_index' => 'Back to the index',
|
||||
'cant_logout_guard' => 'Firefly III can\'t log you out.',
|
||||
'external_url' => 'External URL',
|
||||
'internal_reference' => 'Internal reference',
|
||||
'authorization_request' => 'Firefly III v:version Authorization Request',
|
||||
'authorization_request_intro' => 'Application "<strong>:client</strong>" is requesting permission to access your financial administration. Would you like to authorize <strong>:client</strong> to access these records?',
|
||||
'authorization_request_site' => 'You will be redirected to <code>:url</code> which will then be able to access your Firefly III data.',
|
||||
'authorization_request_invalid' => 'This access request is invalid. Please never follow this link again.',
|
||||
'scopes_will_be_able' => 'This application will be able to:',
|
||||
'button_authorize' => 'Authorize',
|
||||
'none_in_select_list' => '(none)',
|
||||
'no_piggy_bank' => '(no piggy bank)',
|
||||
'name_in_currency' => ':name in :currency',
|
||||
'paid_in_currency' => 'Paid in :currency',
|
||||
'unpaid_in_currency' => 'Unpaid in :currency',
|
||||
'is_alpha_warning' => 'You are running an ALPHA version. Be wary of bugs and issues.',
|
||||
'is_beta_warning' => 'You are running an BETA version. Be wary of bugs and issues.',
|
||||
'all_destination_accounts' => 'Destination accounts',
|
||||
'all_source_accounts' => 'Source accounts',
|
||||
'back_to_index' => 'Back to the index',
|
||||
'cant_logout_guard' => 'Firefly III can\'t log you out.',
|
||||
'external_url' => 'External URL',
|
||||
'internal_reference' => 'Internal reference',
|
||||
|
||||
// check for updates:
|
||||
'update_check_title' => 'Check for updates',
|
||||
'admin_update_check_title' => 'Automatically check for update',
|
||||
'admin_update_check_explain' => 'Firefly III can check for updates automatically. When you enable this setting, it will contact the Firefly III update server to see if a new version of Firefly III is available. When it is, you will get a notification. You can test this notification using the button on the right. Please indicate below if you want Firefly III to check for updates.',
|
||||
'check_for_updates_permission' => 'Firefly III can check for updates, but it needs your permission to do so. Please go to the <a href=":link">administration</a> to indicate if you would like this feature to be enabled.',
|
||||
'updates_ask_me_later' => 'Ask me later',
|
||||
'updates_do_not_check' => 'Do not check for updates',
|
||||
'updates_enable_check' => 'Enable the check for updates',
|
||||
'admin_update_check_now_title' => 'Check for updates now',
|
||||
'admin_update_check_now_explain' => 'If you press the button, Firefly III will see if your current version is the latest.',
|
||||
'check_for_updates_button' => 'Check now!',
|
||||
'update_new_version_alert' => 'A new version of Firefly III is available. You are running :your_version, the latest version is :new_version which was released on :date.',
|
||||
'update_version_beta' => 'This version is a BETA version. You may run into issues.',
|
||||
'update_version_alpha' => 'This version is a ALPHA version. You may run into issues.',
|
||||
'update_current_version_alert' => 'You are running :version, which is the latest available release.',
|
||||
'update_newer_version_alert' => 'You are running :your_version, which is newer than the latest release, :new_version.',
|
||||
'update_check_error' => 'An error occurred while checking for updates: :error',
|
||||
'unknown_error' => 'Unknown error. Sorry about that.',
|
||||
'just_new_release' => 'A new version is available! Version :version was released :date. This release is very fresh. Wait a few days for the new release to stabilize.',
|
||||
'disabled_but_check' => 'You disabled update checking. So don\'t forget to check for updates yourself every now and then. Thank you!',
|
||||
'admin_update_channel_title' => 'Update channel',
|
||||
'admin_update_channel_explain' => 'Firefly III has three update "channels" which determine how ahead of the curve you are in terms of features, enhancements and bugs. Use the "beta" channel if you\'re adventurous and the "alpha" when you like to live life dangerously.',
|
||||
'update_channel_stable' => 'Stable. Everything should work as expected.',
|
||||
'update_channel_beta' => 'Beta. New features but things may be broken.',
|
||||
'update_channel_alpha' => 'Alpha. We throw stuff in, and use whatever sticks.',
|
||||
'update_check_title' => 'Check for updates',
|
||||
'admin_update_check_title' => 'Automatically check for update',
|
||||
'admin_update_check_explain' => 'Firefly III can check for updates automatically. When you enable this setting, it will contact the Firefly III update server to see if a new version of Firefly III is available. When it is, you will get a notification. You can test this notification using the button on the right. Please indicate below if you want Firefly III to check for updates.',
|
||||
'check_for_updates_permission' => 'Firefly III can check for updates, but it needs your permission to do so. Please go to the <a href=":link">administration</a> to indicate if you would like this feature to be enabled.',
|
||||
'updates_ask_me_later' => 'Ask me later',
|
||||
'updates_do_not_check' => 'Do not check for updates',
|
||||
'updates_enable_check' => 'Enable the check for updates',
|
||||
'admin_update_check_now_title' => 'Check for updates now',
|
||||
'admin_update_check_now_explain' => 'If you press the button, Firefly III will see if your current version is the latest.',
|
||||
'check_for_updates_button' => 'Check now!',
|
||||
'update_new_version_alert' => 'A new version of Firefly III is available. You are running :your_version, the latest version is :new_version which was released on :date.',
|
||||
'update_version_beta' => 'This version is a BETA version. You may run into issues.',
|
||||
'update_version_alpha' => 'This version is a ALPHA version. You may run into issues.',
|
||||
'update_current_version_alert' => 'You are running :version, which is the latest available release.',
|
||||
'update_newer_version_alert' => 'You are running :your_version, which is newer than the latest release, :new_version.',
|
||||
'update_check_error' => 'An error occurred while checking for updates: :error',
|
||||
'unknown_error' => 'Unknown error. Sorry about that.',
|
||||
'just_new_release' => 'A new version is available! Version :version was released :date. This release is very fresh. Wait a few days for the new release to stabilize.',
|
||||
'disabled_but_check' => 'You disabled update checking. So don\'t forget to check for updates yourself every now and then. Thank you!',
|
||||
'admin_update_channel_title' => 'Update channel',
|
||||
'admin_update_channel_explain' => 'Firefly III has three update "channels" which determine how ahead of the curve you are in terms of features, enhancements and bugs. Use the "beta" channel if you\'re adventurous and the "alpha" when you like to live life dangerously.',
|
||||
'update_channel_stable' => 'Stable. Everything should work as expected.',
|
||||
'update_channel_beta' => 'Beta. New features but things may be broken.',
|
||||
'update_channel_alpha' => 'Alpha. We throw stuff in, and use whatever sticks.',
|
||||
|
||||
// search
|
||||
'search' => 'Search',
|
||||
'search_query' => 'Query',
|
||||
'search_found_transactions' => 'Firefly III found :count transaction in :time seconds.|Firefly III found :count transactions in :time seconds.',
|
||||
'search_found_more_transactions' => 'Firefly III found more than :count transactions in :time seconds.',
|
||||
'search_for_query' => 'Firefly III is searching for transactions with all of these words in them: <span class="text-info">:query</span>',
|
||||
'invalid_operators_list' => 'These search parameters are not valid and have been ignored.',
|
||||
'search_modifier_date_is' => 'Transaction date is ":value"',
|
||||
'search_modifier_id' => 'Transaction ID is ":value"',
|
||||
'search_modifier_date_before' => 'Transaction date is before or on ":value"',
|
||||
'search_modifier_date_after' => 'Transaction date is after or on ":value"',
|
||||
'search_modifier_created_on' => 'Transaction was created on ":value"',
|
||||
'search_modifier_updated_on' => 'Transaction was last updated on ":value"',
|
||||
'search_modifier_external_id' => 'External ID is ":value"',
|
||||
'search_modifier_no_external_url' => 'The transaction has no external URL',
|
||||
'search_modifier_any_external_url' => 'The transaction must have a (any) external URL',
|
||||
'search_modifier_internal_reference' => 'Internal reference is ":value"',
|
||||
'search_modifier_description_starts' => 'Description is ":value"',
|
||||
'search_modifier_description_ends' => 'Description ends with ":value"',
|
||||
'search_modifier_description_contains' => 'Description contains ":value"',
|
||||
'search_modifier_description_is' => 'Description is exactly ":value"',
|
||||
'search_modifier_currency_is' => 'Transaction (foreign) currency is ":value"',
|
||||
'search_modifier_foreign_currency_is' => 'Transaction foreign currency is ":value"',
|
||||
'search_modifier_has_attachments' => 'The transaction must have an attachment',
|
||||
'search_modifier_has_no_category' => 'The transaction must have no category',
|
||||
'search_modifier_has_any_category' => 'The transaction must have a (any) category',
|
||||
'search_modifier_has_no_budget' => 'The transaction must have no budget',
|
||||
'search_modifier_has_any_budget' => 'The transaction must have a (any) budget',
|
||||
'search_modifier_has_no_bill' => 'The transaction must have no bill',
|
||||
'search_modifier_has_any_bill' => 'The transaction must have a (any) bill',
|
||||
'search_modifier_has_no_tag' => 'The transaction must have no tags',
|
||||
'search_modifier_has_any_tag' => 'The transaction must have a (any) tag',
|
||||
'search_modifier_notes_contain' => 'The transaction notes contain ":value"',
|
||||
'search_modifier_notes_start' => 'The transaction notes start with ":value"',
|
||||
'search_modifier_notes_end' => 'The transaction notes end with ":value"',
|
||||
'search_modifier_notes_are' => 'The transaction notes are exactly ":value"',
|
||||
'search_modifier_no_notes' => 'The transaction has no notes',
|
||||
'search_modifier_any_notes' => 'The transaction must have notes',
|
||||
'search_modifier_amount_exactly' => 'Amount is exactly :value',
|
||||
'search_modifier_amount_less' => 'Amount is less than or equal to :value',
|
||||
'search_modifier_amount_more' => 'Amount is more than or equal to :value',
|
||||
'search_modifier_source_account_is' => 'Source account name is exactly ":value"',
|
||||
'search_modifier_source_account_contains' => 'Source account name contains ":value"',
|
||||
'search_modifier_source_account_starts' => 'Source account name starts with ":value"',
|
||||
'search_modifier_source_account_ends' => 'Source account name ends with ":value"',
|
||||
'search_modifier_source_account_id' => 'Source account ID is :value',
|
||||
'search_modifier_source_account_nr_is' => 'Source account number (IBAN) is ":value"',
|
||||
'search_modifier_source_account_nr_contains' => 'Source account number (IBAN) contains ":value"',
|
||||
'search_modifier_source_account_nr_starts' => 'Source account number (IBAN) starts with ":value"',
|
||||
'search_modifier_source_account_nr_ends' => 'Source account number (IBAN) ends with ":value"',
|
||||
'search_modifier_destination_account_is' => 'Destination account name is exactly ":value"',
|
||||
'search_modifier_destination_account_contains' => 'Destination account name contains ":value"',
|
||||
'search_modifier_destination_account_starts' => 'Destination account name starts with ":value"',
|
||||
'search_modifier_destination_account_ends' => 'Destination account name ends with ":value"',
|
||||
'search_modifier_destination_account_id' => 'Destination account ID is :value',
|
||||
'search_modifier_destination_is_cash' => 'Destination account is (cash) account',
|
||||
'search_modifier_source_is_cash' => 'Source account is (cash) account',
|
||||
'search_modifier_destination_account_nr_is' => 'Destination account number (IBAN) is ":value"',
|
||||
'search_modifier_destination_account_nr_contains' => 'Destination account number (IBAN) contains ":value"',
|
||||
'search_modifier_destination_account_nr_starts' => 'Destination account number (IBAN) starts with ":value"',
|
||||
'search_modifier_destination_account_nr_ends' => 'Destination account number (IBAN) ends with ":value"',
|
||||
'search_modifier_account_id' => 'Source or destination account ID\'s is/are: :value',
|
||||
'search_modifier_category_is' => 'Category is ":value"',
|
||||
'search_modifier_budget_is' => 'Budget is ":value"',
|
||||
'search_modifier_bill_is' => 'Bill is ":value"',
|
||||
'search_modifier_transaction_type' => 'Transaction type is ":value"',
|
||||
'search_modifier_tag_is' => 'Tag is ":value"',
|
||||
'search_modifier_date_is_year' => 'Transaction is in year ":value"',
|
||||
'search_modifier_date_is_month' => 'Transaction is in month ":value"',
|
||||
'search_modifier_date_is_day' => 'Transaction is on day of month ":value"',
|
||||
'search_modifier_date_before_year' => 'Transaction is before or in year ":value"',
|
||||
'search_modifier_date_before_month' => 'Transaction is before or in month ":value"',
|
||||
'search_modifier_date_before_day' => 'Transaction is before or on day of month ":value"',
|
||||
'search_modifier_date_after_year' => 'Transaction is in or after year ":value"',
|
||||
'search_modifier_date_after_month' => 'Transaction is in or after month ":value"',
|
||||
'search_modifier_date_after_day' => 'Transaction is after or on day of month ":value"',
|
||||
'search' => 'Search',
|
||||
'search_query' => 'Query',
|
||||
'search_found_transactions' => 'Firefly III found :count transaction in :time seconds.|Firefly III found :count transactions in :time seconds.',
|
||||
'search_found_more_transactions' => 'Firefly III found more than :count transactions in :time seconds.',
|
||||
'search_for_query' => 'Firefly III is searching for transactions with all of these words in them: <span class="text-info">:query</span>',
|
||||
'invalid_operators_list' => 'These search parameters are not valid and have been ignored.',
|
||||
|
||||
// old
|
||||
|
||||
'search_modifier_date_is' => 'Transaction date is ":value"',
|
||||
'search_modifier_id' => 'Transaction ID is ":value"',
|
||||
'search_modifier_date_before' => 'Transaction date is before or on ":value"',
|
||||
'search_modifier_date_after' => 'Transaction date is after or on ":value"',
|
||||
'search_modifier_external_id_is' => 'External ID is ":value"',
|
||||
'search_modifier_no_external_url' => 'The transaction has no external URL',
|
||||
'search_modifier_any_external_url' => 'The transaction must have a (any) external URL',
|
||||
'search_modifier_internal_reference_is' => 'Internal reference is ":value"',
|
||||
'search_modifier_description_starts' => 'Description is ":value"',
|
||||
'search_modifier_description_ends' => 'Description ends with ":value"',
|
||||
'search_modifier_description_contains' => 'Description contains ":value"',
|
||||
'search_modifier_description_is' => 'Description is exactly ":value"',
|
||||
'search_modifier_currency_is' => 'Transaction (foreign) currency is ":value"',
|
||||
'search_modifier_foreign_currency_is' => 'Transaction foreign currency is ":value"',
|
||||
'search_modifier_has_attachments' => 'The transaction must have an attachment',
|
||||
'search_modifier_has_no_category' => 'The transaction must have no category',
|
||||
'search_modifier_has_any_category' => 'The transaction must have a (any) category',
|
||||
'search_modifier_has_no_budget' => 'The transaction must have no budget',
|
||||
'search_modifier_has_any_budget' => 'The transaction must have a (any) budget',
|
||||
'search_modifier_has_no_bill' => 'The transaction must have no bill',
|
||||
'search_modifier_has_any_bill' => 'The transaction must have a (any) bill',
|
||||
'search_modifier_has_no_tag' => 'The transaction must have no tags',
|
||||
'search_modifier_has_any_tag' => 'The transaction must have a (any) tag',
|
||||
'search_modifier_notes_contains' => 'The transaction notes contain ":value"',
|
||||
'search_modifier_notes_starts' => 'The transaction notes start with ":value"',
|
||||
'search_modifier_notes_ends' => 'The transaction notes end with ":value"',
|
||||
'search_modifier_notes_is' => 'The transaction notes are exactly ":value"',
|
||||
'search_modifier_no_notes' => 'The transaction has no notes',
|
||||
'search_modifier_any_notes' => 'The transaction must have notes',
|
||||
'search_modifier_amount_is' => 'Amount is exactly :value',
|
||||
'search_modifier_amount_less' => 'Amount is less than or equal to :value',
|
||||
'search_modifier_amount_more' => 'Amount is more than or equal to :value',
|
||||
'search_modifier_source_account_is' => 'Source account name is exactly ":value"',
|
||||
'search_modifier_source_account_contains' => 'Source account name contains ":value"',
|
||||
'search_modifier_source_account_starts' => 'Source account name starts with ":value"',
|
||||
'search_modifier_source_account_ends' => 'Source account name ends with ":value"',
|
||||
'search_modifier_source_account_id' => 'Source account ID is :value',
|
||||
'search_modifier_source_account_nr_is' => 'Source account number (IBAN) is ":value"',
|
||||
'search_modifier_source_account_nr_contains' => 'Source account number (IBAN) contains ":value"',
|
||||
'search_modifier_source_account_nr_starts' => 'Source account number (IBAN) starts with ":value"',
|
||||
'search_modifier_source_account_nr_ends' => 'Source account number (IBAN) ends with ":value"',
|
||||
'search_modifier_destination_account_is' => 'Destination account name is exactly ":value"',
|
||||
'search_modifier_destination_account_contains' => 'Destination account name contains ":value"',
|
||||
'search_modifier_destination_account_starts' => 'Destination account name starts with ":value"',
|
||||
'search_modifier_destination_account_ends' => 'Destination account name ends with ":value"',
|
||||
'search_modifier_destination_account_id' => 'Destination account ID is :value',
|
||||
'search_modifier_destination_is_cash' => 'Destination account is (cash) account',
|
||||
'search_modifier_source_is_cash' => 'Source account is (cash) account',
|
||||
'search_modifier_destination_account_nr_is' => 'Destination account number (IBAN) is ":value"',
|
||||
'search_modifier_destination_account_nr_contains' => 'Destination account number (IBAN) contains ":value"',
|
||||
'search_modifier_destination_account_nr_starts' => 'Destination account number (IBAN) starts with ":value"',
|
||||
'search_modifier_destination_account_nr_ends' => 'Destination account number (IBAN) ends with ":value"',
|
||||
'search_modifier_account_id' => 'Source or destination account ID\'s is/are: :value',
|
||||
'search_modifier_category_is' => 'Category is ":value"',
|
||||
'search_modifier_budget_is' => 'Budget is ":value"',
|
||||
'search_modifier_bill_is' => 'Bill is ":value"',
|
||||
'search_modifier_transaction_type' => 'Transaction type is ":value"',
|
||||
'search_modifier_tag_is' => 'Tag is ":value"',
|
||||
'search_modifier_date_on_year' => 'Transaction is in year ":value"',
|
||||
'search_modifier_date_on_month' => 'Transaction is in month ":value"',
|
||||
'search_modifier_date_on_day' => 'Transaction is on day of month ":value"',
|
||||
'search_modifier_date_before_year' => 'Transaction is before or in year ":value"',
|
||||
'search_modifier_date_before_month' => 'Transaction is before or in month ":value"',
|
||||
'search_modifier_date_before_day' => 'Transaction is before or on day of month ":value"',
|
||||
'search_modifier_date_after_year' => 'Transaction is in or after year ":value"',
|
||||
'search_modifier_date_after_month' => 'Transaction is in or after month ":value"',
|
||||
'search_modifier_date_after_day' => 'Transaction is after or on day of month ":value"',
|
||||
|
||||
|
||||
// new
|
||||
'search_modifier_tag_is_not' => 'No tag is ":value"',
|
||||
|
||||
'search_modifier_account_is' => 'Either account is ":value"',
|
||||
'search_modifier_account_contains' => 'Either account contains ":value"',
|
||||
'search_modifier_account_ends' => 'Either account ends with ":value"',
|
||||
'search_modifier_account_starts' => 'Either account starts with ":value"',
|
||||
'search_modifier_account_nr_is' => 'Either account number / IBAN is ":value"',
|
||||
'search_modifier_account_nr_contains' => 'Either account number / IBAN contains ":value"',
|
||||
'search_modifier_account_nr_ends' => 'Either account number / IBAN ends with ":value"',
|
||||
'search_modifier_account_nr_starts' => 'Either account number / IBAN starts with ":value"',
|
||||
'search_modifier_category_contains' => 'Category contains ":value"',
|
||||
'search_modifier_category_ends' => 'Category ends with ":value"',
|
||||
'search_modifier_category_starts' => 'Category starts with ":value"',
|
||||
'search_modifier_budget_contains' => 'Budget contains ":value"',
|
||||
'search_modifier_budget_ends' => 'Budget ends with ":value"',
|
||||
'search_modifier_budget_starts' => 'Budget starts with ":value"',
|
||||
'search_modifier_bill_contains' => 'Bill contains ":value"',
|
||||
'search_modifier_bill_ends' => 'Bill ends with ":value"',
|
||||
'search_modifier_bill_starts' => 'Bill starts with ":value"',
|
||||
'search_modifier_external_id_contains' => 'External ID contains ":value"',
|
||||
'search_modifier_external_id_ends' => 'External ID ends with ":value"',
|
||||
'search_modifier_external_id_starts' => 'External ID starts with ":value"',
|
||||
'search_modifier_internal_reference_contains' => 'Internal reference contains ":value"',
|
||||
'search_modifier_internal_reference_ends' => 'Internal reference ends with ":value"',
|
||||
'search_modifier_internal_reference_starts' => 'Internal reference starts with ":value"',
|
||||
'search_modifier_external_url_is' => 'External URL is ":value"',
|
||||
'search_modifier_external_url_contains' => 'External URL contains ":value"',
|
||||
'search_modifier_external_url_ends' => 'External URL ends with ":value"',
|
||||
'search_modifier_external_url_starts' => 'External URL starts with ":value"',
|
||||
'search_modifier_has_no_attachments' => 'Transaction has no attachments',
|
||||
'search_modifier_account_is_cash' => 'Either account is a cash account.',
|
||||
'search_modifier_journal_id' => 'The journal ID is ":value"',
|
||||
'search_modifier_recurrence_id' => 'The recurring transaction ID is ":value"',
|
||||
'search_modifier_foreign_amount_is' => 'The foreign amount is ":value"',
|
||||
'search_modifier_foreign_amount_less' => 'The foreign amount is less than ":value"',
|
||||
'search_modifier_foreign_amount_more' => 'The foreign amount is more than ":value"',
|
||||
|
||||
// date fields
|
||||
'search_modifier_interest_date_on_year' => 'Transaction interest date is in year ":value"',
|
||||
'search_modifier_interest_date_on_month' => 'Transaction interest date is in month ":value"',
|
||||
'search_modifier_interest_date_on_day' => 'Transaction interest date is on day of month ":value"',
|
||||
'search_modifier_interest_date_before_year' => 'Transaction interest date is before or in year ":value"',
|
||||
'search_modifier_interest_date_before_month' => 'Transaction interest date is before or in month ":value"',
|
||||
'search_modifier_interest_date_before_day' => 'Transaction interest date is before or on day of month ":value"',
|
||||
'search_modifier_interest_date_after_year' => 'Transaction interest date is after or in year ":value"',
|
||||
'search_modifier_interest_date_after_month' => 'Transaction interest date is after or in month ":value"',
|
||||
'search_modifier_interest_date_after_day' => 'Transaction interest date is after or on day of month ":value"',
|
||||
'search_modifier_book_date_on_year' => 'Transaction book date is in year ":value"',
|
||||
'search_modifier_book_date_on_month' => 'Transaction book date is in month ":value"',
|
||||
'search_modifier_book_date_on_day' => 'Transaction book date is on day of month ":value"',
|
||||
'search_modifier_book_date_before_year' => 'Transaction book date is before or in year ":value"',
|
||||
'search_modifier_book_date_before_month' => 'Transaction book date is before or in month ":value"',
|
||||
'search_modifier_book_date_before_day' => 'Transaction book date is before or on day of month ":value"',
|
||||
'search_modifier_book_date_after_year' => 'Transaction book date is after or in year ":value"',
|
||||
'search_modifier_book_date_after_month' => 'Transaction book date is after or in month ":value"',
|
||||
'search_modifier_book_date_after_day' => 'Transaction book date is after or on day of month ":value"',
|
||||
'search_modifier_process_date_on_year' => 'Transaction process date is in year ":value"',
|
||||
'search_modifier_process_date_on_month' => 'Transaction process date is in month ":value"',
|
||||
'search_modifier_process_date_on_day' => 'Transaction process date is on day of month ":value"',
|
||||
'search_modifier_process_date_before_year' => 'Transaction process date is before or in year ":value"',
|
||||
'search_modifier_process_date_before_month' => 'Transaction process date is before or in month ":value"',
|
||||
'search_modifier_process_date_before_day' => 'Transaction process date is before or on day of month ":value"',
|
||||
'search_modifier_process_date_after_year' => 'Transaction process date is after or in year ":value"',
|
||||
'search_modifier_process_date_after_month' => 'Transaction process date is after or in month ":value"',
|
||||
'search_modifier_process_date_after_day' => 'Transaction process date is after or on day of month ":value"',
|
||||
'search_modifier_due_date_on_year' => 'Transaction due date is in year ":value"',
|
||||
'search_modifier_due_date_on_month' => 'Transaction due date is in month ":value"',
|
||||
'search_modifier_due_date_on_day' => 'Transaction due date is on day of month ":value"',
|
||||
'search_modifier_due_date_before_year' => 'Transaction due date is before or in year ":value"',
|
||||
'search_modifier_due_date_before_month' => 'Transaction due date is before or in month ":value"',
|
||||
'search_modifier_due_date_before_day' => 'Transaction due date is before or on day of month ":value"',
|
||||
'search_modifier_due_date_after_year' => 'Transaction due date is after or in year ":value"',
|
||||
'search_modifier_due_date_after_month' => 'Transaction due date is after or in month ":value"',
|
||||
'search_modifier_due_date_after_day' => 'Transaction due date is after or on day of month ":value"',
|
||||
'search_modifier_payment_date_on_year' => 'Transaction payment date is in year ":value"',
|
||||
'search_modifier_payment_date_on_month' => 'Transaction payment date is in month ":value"',
|
||||
'search_modifier_payment_date_on_day' => 'Transaction payment date is on day of month ":value"',
|
||||
'search_modifier_payment_date_before_year' => 'Transaction payment date is before or in year ":value"',
|
||||
'search_modifier_payment_date_before_month' => 'Transaction payment date is before or in month ":value"',
|
||||
'search_modifier_payment_date_before_day' => 'Transaction payment date is before or on day of month ":value"',
|
||||
'search_modifier_payment_date_after_year' => 'Transaction payment date is after or in year ":value"',
|
||||
'search_modifier_payment_date_after_month' => 'Transaction payment date is after or in month ":value"',
|
||||
'search_modifier_payment_date_after_day' => 'Transaction payment date is after or on day of month ":value"',
|
||||
'search_modifier_invoice_date_on_year' => 'Transaction invoice date is in year ":value"',
|
||||
'search_modifier_invoice_date_on_month' => 'Transaction invoice date is in month ":value"',
|
||||
'search_modifier_invoice_date_on_day' => 'Transaction invoice date is on day of month ":value"',
|
||||
'search_modifier_invoice_date_before_year' => 'Transaction invoice date is before or in year ":value"',
|
||||
'search_modifier_invoice_date_before_month' => 'Transaction invoice date is before or in month ":value"',
|
||||
'search_modifier_invoice_date_before_day' => 'Transaction invoice date is before or on day of month ":value"',
|
||||
'search_modifier_invoice_date_after_year' => 'Transaction invoice date is after or in year ":value"',
|
||||
'search_modifier_invoice_date_after_month' => 'Transaction invoice date is after or in month ":value"',
|
||||
'search_modifier_invoice_date_after_day' => 'Transaction invoice date is after or on day of month ":value"',
|
||||
'search_modifier_updated_at_on_year' => 'Transaction was last updated in year ":value"',
|
||||
'search_modifier_updated_at_on_month' => 'Transaction was last updated in month ":value"',
|
||||
'search_modifier_updated_at_on_day' => 'Transaction was last updated on day of month ":value"',
|
||||
'search_modifier_updated_at_before_year' => 'Transaction was last updated in or before year ":value"',
|
||||
'search_modifier_updated_at_before_month' => 'Transaction was last updated in or before month ":value"',
|
||||
'search_modifier_updated_at_before_day' => 'Transaction was last updated on or before day of month ":value"',
|
||||
'search_modifier_updated_at_after_year' => 'Transaction was last updated in or after year ":value"',
|
||||
'search_modifier_updated_at_after_month' => 'Transaction was last updated in or after month ":value"',
|
||||
'search_modifier_updated_at_after_day' => 'Transaction was last updated on or after day of month ":value"',
|
||||
'search_modifier_created_at_on_year' => 'Transaction was created in year ":value"',
|
||||
'search_modifier_created_at_on_month' => 'Transaction was created in month ":value"',
|
||||
'search_modifier_created_at_on_day' => 'Transaction was created on day of month ":value"',
|
||||
'search_modifier_created_at_before_year' => 'Transaction was created in or before year ":value"',
|
||||
'search_modifier_created_at_before_month' => 'Transaction was created in or before month ":value"',
|
||||
'search_modifier_created_at_before_day' => 'Transaction was created on or before day of month ":value"',
|
||||
'search_modifier_created_at_after_year' => 'Transaction was created in or after year ":value"',
|
||||
'search_modifier_created_at_after_month' => 'Transaction was created in or after month ":value"',
|
||||
'search_modifier_created_at_after_day' => 'Transaction was created on or after day of month ":value"',
|
||||
|
||||
|
||||
'update_rule_from_query' => 'Update rule ":rule" from search query',
|
||||
'create_rule_from_query' => 'Create new rule from search query',
|
||||
'rule_from_search_words' => 'The rule engine has a hard time handling ":string". The suggested rule that fits your search query may give different results. Please verify the rule triggers carefully.',
|
||||
|
Loading…
Reference in New Issue
Block a user