Files
T
2026-10-29 15:24:06 +01:00

2471 lines
131 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Generated, do not edit. sha256:a167e18e55f858b6191c5f1c50bdab5b3bf485873744837c0e096e77f639cd0e
import { nl } from './nl.js';
export const en = {
app: { name: 'Atreides Assets' },
common: {
loading: 'Loading…',
loadError: 'Cannot load data',
manageAssets: 'Manage assets',
sessionExpired: 'The session has expired. You are being sent to the sign-in screen.',
backendSilent: 'The backend does not respond within {s} seconds. Is the server process running?',
requestTooLarge: 'The request is too large.',
fileTooLarge: 'The file is too large.',
invalidAmount: 'Invalid amount.',
},
splash: {
quote: nl.splash.quote,
logoHint: 'Show the splash screen',
},
attention: {
title: 'Needs attention',
none: 'Nothing needs attention',
integrationNoKeySuffix: ': API key required, not yet entered',
priceGaps: 'Price history: {n} gaps to fill',
usageNear: '{naam}: {calls} of {limiet} calls this month',
usageOver: '{naam}: monthly limit reached ({calls} of {limiet})',
actionsReconcilePrefix: 'Reconcile: ',
actionsReconcileSuffix: ' open',
actionsInterestPrefix: 'Interest to record: ',
actionsValuationPrefix: 'Valuation differences: ',
actionsAiPrefix: 'AI proposals: ',
actionsReservationPrefix: 'Reservations to settle: ',
healthPrefix: 'Findings about your records: ',
backupNever: 'No backup made yet',
backupStalePrefix: 'Last backup ',
backupStaleSuffix: ' days ago',
healthNever: 'Records never checked',
healthStalePrefix: 'Last check ',
healthStaleSuffix: ' days ago',
aiActivityPrefix: 'AI activity: ',
aiActivitySuffix: ' new call(s)',
licenseChanged: 'The license has changed',
},
commands: {
goingTo: 'An AI is taking you to',
stop: 'Stop',
goNow: 'Go now',
goAlways: 'Always go now',
movedTo: 'An AI took you to',
countdownBack: 'Count down anyway',
stopped: 'Stopped by the user.',
badTarget: 'The command did not point to a valid place in the app.',
tooLate: 'The command had almost expired when this tab picked it up; no navigation took place.',
unknownKind: 'This tab does not know this kind of command.',
},
license: {
lockedTitle: 'Part of the paid version',
counter: '{naam} in the free edition: {n} of {max}',
whatIsPaid: 'What does the paid version include?',
why_develop: 'Development version: nothing is restricted below 1.0.0',
why_forced: 'Forced via ASSETAPP_LICENSE_STATE (development only)',
'why_forced-develop': 'Forced via ASSETAPP_LICENSE_STATE (development only)',
why_none: 'No license file found',
why_invalid: 'The license file is not valid',
why_unreadable: 'The license file cannot be read',
'why_out-of-range': 'The license does not cover this major version',
'why_unknown-version': 'The app version cannot be determined',
why_licensed: 'Valid license',
cardTitle: 'License',
cardFree: 'This installation runs the free version: no time limit, with a small set of records and '
+ 'without the connections, the source choice and the taxes page. Reading and exporting always '
+ 'keep working; nothing is ever removed.',
cardBuy: 'The paid version lifts those limits. If you have a license file, drop it below.',
cardFull: 'This installation runs the full version. All limits are lifted and every feature is '
+ 'available.',
cardDevelop: 'This is a development version: below 1.0.0 the app restricts nothing.',
cardFacts: 'The license is for {buyer}, issued on {issued} and valid for major versions {from} '
+ 'through {to}.',
cardOutOfRange: 'This app is version {version} and falls outside that range.',
cardProblem: 'There is a license file, but the app cannot use it.',
cardVersion: 'Version {version}',
signInTitle: 'Sign in',
signInIntro: 'Your license belongs to a nostr key. Sign in to fetch the licenses for that key.',
signInLast: 'Last signed in as {npub}.',
signInExtension: 'With extension',
signInExtensionNone: 'No nostr extension found in this browser (such as Alby or nos2x).',
signInKey: 'With key',
signInNew: 'New key',
signInKeyLabel: 'Secret key (nsec)',
signInKeyHint: 'The key stays in this tab and is not stored anywhere. After a reload you sign in '
+ 'again.',
signInGo: 'Sign in',
signInBadKey: 'This is not a valid secret key. An nsec starts with nsec1.',
signInNpub: 'This is the public key (npub). Signing in requires the secret key (nsec).',
newKeyTitle: 'Your new key',
newKeyIntro: 'Keep this secret key safe. Whoever has it can fetch your license; if you lose it, you '
+ 'can no longer do so. The app does not store it.',
newKeyPublic: 'Public key: {npub}',
newKeyCopy: 'Copy',
newKeyCopied: 'Copied',
newKeyDownload: 'Download',
newKeySaved: 'I have saved this key',
newKeyGo: 'Continue',
newKeyCancel: 'Cancel',
newKeyFileName: 'nostr-key.txt',
signedIn: 'Signed in as {npub}.',
signedInExtension: 'Signed in as {npub}, with extension.',
signOut: 'Sign out',
otherBuyer: 'The installed license belongs to a different key.',
licensesLoading: 'Fetching licenses…',
licensesNone: 'There are no licenses for this key yet.',
licenseLine: '{level}, major versions {from} through {to}, issued on {issued}.',
level_full: 'Full version',
level_free: 'Free version',
licenseInstalled: 'Installed',
licenseInstall: 'Install',
licenseNotValid: 'This app does not accept this license.',
licenseNotCovered: 'Does not cover this version.',
buyTitle: 'Buy',
buyPrice: 'A full license for major version {major} costs {sats} sats.',
buyClosed: 'Sales are closed at the moment.',
buyAway: 'Atreides Services cannot be reached right now, so buying is not possible at the moment. '
+ 'Try again later.',
buySignInFirst: 'Sign in first: the license is issued to your key.',
buyButton: 'Buy',
buyInvoice: 'Pay this invoice with a Lightning wallet. It is valid until {time}.',
buyOpenWallet: 'Open in wallet',
buyQr: 'QR code of the invoice, to scan with a wallet',
buyCopy: 'Copy invoice',
buyCopied: 'Copied',
buyWaiting: 'Waiting for payment…',
buyPaid: 'Paid. The license is being issued…',
buyWaived: 'Waived. The license is being issued…',
buyExpired: 'The invoice expired without payment.',
buyCanceled: 'The invoice was canceled.',
buyUnderpaid: 'Less than the amount was paid; contact the seller.',
buyAgain: 'New order',
buyNotValid: 'The license was issued, but this app does not accept it. Contact the seller.',
supportTitle: 'Support',
supportIntro: 'A conversation with the seller, via Atreides Services. Your messages are sent from your '
+ 'signed-in key, and you read the reply here. You can attach a screenshot.',
supportAway: 'Atreides Services cannot be reached right now, so support is not available at the '
+ 'moment. Try again later.',
supportNostr: 'Prefer nostr? Send a direct message to {name}.',
supportLabel: 'Your message',
supportPlaceholder: 'Type a message…',
supportSend: 'Send',
supportSending: 'Sending…',
supportEmpty: 'Type a message or choose a screenshot first.',
supportTooLong: 'A message is at most {max} characters.',
supportAttach: 'Screenshot',
supportAttachHint: 'PNG, JPEG or WebP up to {mb} MB; pasting also works.',
supportAttachType: 'A screenshot is a PNG, JPEG or WebP image.',
supportAttachTooLarge: 'A screenshot is at most {mb} MB.',
supportRemoveAttachment: 'Remove screenshot',
supportScreenshot: 'Screenshot',
supportShowScreenshot: 'Show screenshot',
supportRefresh: 'Refresh',
supportThreadLoading: 'Fetching conversation…',
supportThreadEmpty: 'No messages yet. Ask your question below.',
supportYou: 'You',
supportSeller: 'Support',
supportAi: 'Support, drafted with the help of AI',
payTitle: 'Pay with Lightning',
payIntro: "You pay with a Lightning invoice created by the seller's service; the app does not see your "
+ 'wallet. For that you need a wallet with sats.',
payGroup_easy: 'The easiest way, for small amounts',
payGroup_other: 'Other apps',
payApp_phoenix: 'is a Lightning wallet on your phone that runs its own node; the app manages the '
+ 'channel for you. You use it to scan the QR code of the invoice.',
payApp_pocket: 'converts a transfer from your bank account into sats and sends them via Lightning to '
+ 'Phoenix. One-time ID check.',
payApp_strike: 'pays an invoice directly from the app, with money from your bank account. Strike holds '
+ 'the balance and asks for ID at sign-up.',
payApp_zeus: 'runs LND on your phone or connects to your own node, such as one on an Umbrel; you manage '
+ 'channels and funding yourself.',
payApp_bringin: 'is a Lightning wallet with your own keys, and gives you your own IBAN to buy sats (with '
+ 'ID check).',
payNote: 'As of October 2026: check the terms with the provider.',
nostrMore: 'About nostr and your key',
signInKnown: 'Your license is on {npub}. Sign with that key to fetch licenses, buy or ask for '
+ 'support; the npub alone does not prove it is you.',
infoNostrHead: 'What is nostr?',
infoNostr: 'Nostr is an open protocol in which your identity is a key pair. The public key (npub) is '
+ 'like an address: anyone may see it. The secret key (nsec) is like a password that no one can '
+ 'recover for you: whoever has it is you.',
infoWhyHead: 'Why is the license tied to a key?',
infoWhy: 'No account and no email address are needed. The license is signed to your npub and the app '
+ 'verifies it without internet. With the same key you get it back on any installation, even after '
+ 'a reinstall.',
infoSignInHead: 'How do you sign in?',
infoSignIn: 'With a browser extension such as Alby or nos2x, the key stays in the extension and the app '
+ 'never sees it. With the key itself, it stays in this tab and is not stored anywhere. If you do '
+ 'not have a key yet, create one here and keep it safe.',
infoZapHead: 'And a zap?',
infoZap: 'A zap (NIP-57) is a Lightning payment with a nostr receipt attached, meant as a tip under a '
+ 'post. The license does not need one: a regular invoice is enough, and the license is already '
+ 'on your key.',
link_nostrHow: 'nostr.how: what nostr is, for beginners',
link_nostrOrg: 'nostr.org: introduction and apps (by LNbits)',
link_alby: 'Alby: browser extension with nostr and Lightning',
link_nos2x: 'nos2x: browser extension that only signs',
link_lightning: 'lightning.network: the Lightning Network',
infoPrivacyHead: 'What does the seller know about you?',
infoPrivacy: 'Your npub and the orders with it. An email address only if you provide one, and then '
+ 'made unrecognizable, so it can only be matched if you come forward with it yourself.',
name_fiatAccounts: 'Fiat accounts',
name_assets: 'Assets besides currencies',
name_valuations: 'Balances',
name_portfolios: 'Portfolios',
featTitle: 'What the editions include',
featFull: 'Full',
featFree: 'Free',
featFreeOpen: 'What the free edition includes is not settled yet.',
featNoShot: 'No screenshot of this feature yet.',
featIncluded: 'Included',
featExcluded: 'Not included',
featUndecided: 'Not decided yet',
featPartial: 'partly',
featPartialTitle: 'Part of it is included',
featGroup_overview: 'Overview and reports',
featGroup_bitcoin: 'Bitcoin and Lightning',
featGroup_records: 'Records',
featGroup_prices: 'Prices',
featGroup_app: 'The app',
feat_dashboard: 'Dashboard with your own widgets',
feat_wealth: 'Net worth per asset and account',
feat_returns: 'Return per period',
feat_taxes: 'Taxes per reference date',
feat_tracking: 'On-chain wallet tracking',
feat_lightning: 'Lightning via LND and NWC',
feat_interest: 'Interest and rewards',
feat_balances: 'Balances and reconcile',
feat_ownMempool: 'Your own mempool node',
feat_priceHistory: 'Price history',
feat_sourceChoice: 'Source choice per asset',
feat_providerKeys: 'Your own price sources and API keys',
feat_signals: 'Bitcoin signals, charts and widget',
feat_netshare: 'Network share widget',
feat_portfolios: 'Multiple portfolios',
feat_ai: 'AI connection (MCP)',
feat_import: 'Import and export',
feat_data: 'Data: the raw tables',
feat_health: 'Health: checks on your records',
feat_kiosk: 'The app in its own window',
feat_metals: 'Precious metals, coins and bars',
unlimited: 'unlimited',
dropHere: 'Drag the license file here',
dropOr: 'or click to choose one',
dropTooBig: 'That file is far too large for a license. The license file is a small JSON file of a '
+ 'few lines at most.',
installOk: 'License saved. The app is now the full version.',
installOkFuture: 'License saved, but it does not cover this major version. The app stays in the free '
+ 'version for now.',
installUnreadable: 'This is not a valid license file: {reason}',
installBadSignature: 'The signature does not match this license, or it was not issued for this app. '
+ 'Nothing was saved.',
accountsWhat: 'The free version is limited to one fiat account. With a license you enter all your '
+ 'bank and savings accounts, interest included.',
matrixWhat: 'The source choice matrix is part of the paid version. With it you decide per asset '
+ 'which source takes precedence and what the app falls back on; without that choice it uses the '
+ 'default sources.',
aiWhat: 'The AI integration is part of the paid version. With it an AI assistant can read your records '
+ 'and make proposals, with a log of everything that was shared.',
keysWhat: 'Your own provider API keys are part of the paid version. The default sources work without '
+ 'an API key; your own subscription with a price source is entered here.',
taxWhat: 'The taxes page shows your net worth on each reference date and the gain/loss per year, with '
+ 'bank and other assets separate, and shows per item where the number comes from.',
},
connections: {
lightningPaid: 'Lightning connections are part of the paid version.',
ownExplorerPaid: 'Your own explorer is part of the paid version; the default source keeps working.',
kindBtcExplorer: 'Bitcoin Blockchain Explorer',
usedByBtcExplorer: 'Used by: wallet tracking (Tracking), and the price source "mempool" (Providers) if there is one.',
newProfile: 'New profile',
editProfile: 'Edit profile',
name: 'Name',
url: 'Base URL',
save: 'Save',
test: 'Test',
edit: 'Edit',
delete: 'Delete',
active: 'Active',
notTested: 'Not tested',
testing: 'Testing…',
statusOk: 'Connected',
statusFail: 'No connection',
blockHeight: 'block height',
lastChecked: 'Last tested:',
badResponse: 'Unexpected response from the server.',
testUnsupported: 'Testing this kind of connection is not supported yet.',
cspBlocked: 'This address was added after the page loaded, and the browser only allows it after a '
+ 'reload. Reload the page and test again.',
confirmDelete: 'Delete this profile?',
kindLnd: 'Lightning node (LND)',
usedByLnd: 'Used by: the Lightning tracker (coming in B3). The app talks to the node through its own backend: the node is not public; macaroon and tls.cert stay server-side.',
lndUrl: 'LND REST URL',
lndMacaroon: 'Macaroon (hex or base64; read-only baked recommended)',
lndTlsCert: 'tls.cert (PEM; optional: with cert pinned and verified, without cert unverified https)',
secretKeepHint: 'leave empty = unchanged',
lndSynced: 'synced',
lndNotSynced: 'NOT synced',
noActive: 'No active {kind} connection. Choose one at System → Integrations → Connections.',
nameRequired: 'Name is required.',
urlScheme: 'A URL starts with http(s):// or ws(s)://.',
nameInUse: 'A {kind} connection named "{naam}" already exists.',
unknownConnection: 'Connection #{id} does not exist.',
linkedToSources: 'This connection is still linked to {n} tracking source(s); unlink them first.',
macaroonUnknown: 'Macaroon not recognized: paste hex (lncli bakemacaroon) or base64(url), for example the macaroon parameter from an lndconnect URL.',
lndUrlScheme: 'The LND REST URL starts with http:// or https:// (the dialog completes a bare ip:port itself).',
tlsCertPem: 'tls.cert must be a PEM certificate (-----BEGIN CERTIFICATE-----).',
lndUrlMissing: 'The LND REST URL is missing.',
lndNoConfig: 'No LND configuration for this connection: save the URL and the macaroon first.',
lndNoMacaroon: 'No macaroon saved for this connection: edit the profile and paste the macaroon.',
nwcUriInvalid: 'Invalid NWC URI (expected nostr+walletconnect://…?relay=…&secret=…).',
nwcPubkeyInvalid: 'Invalid wallet pubkey in the NWC URI.',
nwcSecretInvalid: 'Invalid secret in the NWC URI.',
nwcRelayInvalid: 'Invalid or missing relay (wss://…) in the NWC URI.',
nwcBadFormat: 'Unexpected NIP-04 format in the response.',
nwcNoUri: 'No NWC URI saved for this source. Edit the source and paste the connection URI.',
lndWantsHttps: 'The node expects https on this port: paste the LND tls.cert into the profile (the app then chooses https with pinning), or type https:// before the address.',
lndTimeout: 'LND timeout ({s}s): the node cannot be reached. Is the (WireGuard) tunnel on?',
lndUnreachable: 'LND cannot be reached: {reden}.',
lndUnreachableCert: 'LND cannot be reached: {reden}. The pinned tls.cert does not match this node: paste the current tls.cert into the profile.',
nwcRelayRefused: 'The relay refuses the request: {reden}.',
nwcRelayRefusedNoReason: 'The relay refuses the request and does not say why.',
nwcDecryptFailed: 'Decrypting the response failed: {reden}',
kindMarket: 'Atreides Services',
usedByMarket: "The app's own price service, for prices, the license and support. Address and token apply to the whole installation, so to every portfolio. The app talks to the service through its own server; the token stays server-side and never comes back to the browser.",
marketConfigure: 'Configure',
marketDialogTitle: 'Configure Atreides Services',
marketTokenUnset: 'no token',
marketTokenLicense: 'token from the license ({tier})',
marketTokenManual: 'custom token',
marketTokenPending: 'the app requests a token with the license',
marketTokenNoLicense: 'no license to request a token with',
marketOverrideUrl: 'development address',
marketTestOk: '{app} {version} · {n} instruments',
marketSpot: 'What the app fetches from the service',
marketSpot_off: 'Only the intraday price line; prices and daily prices from your own sources',
marketSpot_fallback: 'Also prices and daily prices, if your own sources return nothing',
marketSpot_first: 'Also prices and daily prices, before your own sources; a source you chose yourself takes precedence',
marketSpotShort_off: 'service: intraday line only',
marketSpotShort_fallback: 'service: as fallback',
marketSpotShort_first: 'service: first',
},
marketService: {
urlScheme: 'The service address starts with http:// or https://.',
noToken: 'There is no token for Atreides Services, and no license to request one with.',
unreachable: 'Atreides Services cannot be reached at {url}: {reason}. The app continues with the prices it already has.',
timeout: 'Atreides Services does not respond within {s}s. Try again later.',
unauthorized: 'Atreides Services rejects the token, even after the app requested a new one with the license.',
signatureRefused: 'Atreides Services rejects the signature: {reason}',
salesClosed: 'Nothing is for sale at the moment.',
checkoutUnavailable: 'The Atreides Services checkout cannot create an invoice right now. Try again later.',
tooManyOrders: 'Atreides Services is not accepting more orders for this key right now: {reason}',
unknownOrder: 'Atreides Services does not know this order (anymore).',
licenseRevoked: 'Atreides Services has revoked this license and no longer issues a token for it.',
badLicense: 'Atreides Services does not accept this license: {reason}',
supportEmpty: 'A message has text or a screenshot.',
supportTooLong: 'A message is at most {max} characters.',
supportAttachmentType: 'Atreides Services does not accept this screenshot: only a PNG, JPEG or WebP image.',
supportAttachmentTooLarge: 'A screenshot is at most {mb} MB.',
supportTooMany: 'Too many messages came from this key today. Try again tomorrow.',
unknownAttachment: 'Atreides Services does not know this screenshot.',
tooManyRequests: 'Too many requests to Atreides Services. Try again in {s}s.',
monthUnreachable: 'Atreides Services cannot read month {month} right now (the storage cannot be reached). That is not a gap in the prices: try again later.',
spotUnreachable: 'Atreides Services has the latest price, but cannot read it right now (the storage cannot be reached). Try again later.',
sourceLive: 'Atreides Services ({source})',
sourceCached: 'Atreides Services, last known {when} UTC (the service is not responding)',
unavailable: 'Atreides Services is not ready yet, it may still be starting. Try again later.',
badAnswer: 'The response from {url} is not the Atreides Services API. Is this the API port (3855 on the Umbrel, 8091 locally) and not that of the admin app?',
rejected: 'Atreides Services rejects the request (HTTP {status}, {key}): {reason}',
},
nav: {
overview: 'Overview',
manage: 'Manage',
stam: 'Master data',
events: 'Events',
observe: 'Tools',
onchain: 'On-chain',
tax: 'Reports',
tools: 'Bitcoin',
system: 'System',
home: 'Dashboard',
settings: 'Settings',
portfolios: 'Portfolios',
import: 'Import and export',
data: 'Data',
health: 'Health',
ai: 'AI activity',
license: 'License',
integrations: 'Integrations',
connections: 'Connections',
assets: 'Assets',
accounts: 'Accounts',
wealth: 'Wealth',
locations: 'Locations',
labels: 'Labels',
trades: 'Buy & Sell',
transfers: 'Transfers',
valuations: 'Balances',
interest: 'Interest & Rewards',
reservations: 'Reservations',
taxes: 'Taxes',
validation: 'Validation',
tracking: 'Tracking',
conversion: 'Conversion',
'conversion/bitcoin': 'Conversions',
'price-history': 'Price history',
charts: 'Signals & Charts',
actions: 'To do',
guide: 'Help',
customize: 'Customize layout',
},
dashboard: {
width: 'Width',
remove: 'Remove',
settings: 'Settings',
reorder: 'Drag to reorder',
add: 'Add widget',
secondCurrency: 'Second currency',
secondNone: 'None',
momentum: 'Short trend as dot',
momentumUp: '{pct}% of the last {n} price moves up',
momentumDown: '{pct}% of the last {n} price moves down',
addNoFit: 'Not enough space here for the remaining widgets',
addNone: 'Everything has been added',
profile: 'Layout',
profileNew: 'New layout…',
profileNewPrompt: 'Name of the new layout',
profileRename: 'Rename…',
profileRenamePrompt: 'New name for this layout',
profileDelete: 'Delete this layout…',
profileDeleteConfirm: 'Delete this layout and all its widgets? The other layouts remain.',
profileSystemHint: 'The default layout cannot be renamed.',
profileRestart: 'Start default layout over…',
profileRestartConfirm: 'Start the default layout over? What you placed yourself is removed and the default layout takes its place.',
nameRequired: 'A layout needs a name.',
unknownProfile: 'Layout #{id} does not exist.',
lastNotDeletable: 'The last layout cannot be deleted.',
widget: {
signal: 'Bitcoin signals',
notifications: 'To do',
standing: 'Current position',
spot: 'Price',
metrics: 'Status',
netshare: 'Network share',
clocks: 'World clocks',
return: 'Return',
},
},
clocks: {
showExchanges: 'Show exchanges',
chooseClocks: 'Show clocks',
localLabel: 'My time zone',
hoverLocal: 'Your time zone',
hoverSame: 'Same as your time zone',
listHead: 'Exchanges · in your time',
opensAt: 'Opens at {tijd}',
opensOn: 'Opens {dag} at {tijd}',
openUntil: 'Open until {tijd}',
opensIn: 'in {duur}',
closesIn: 'closes in {duur}',
durMin: '{n} min',
durHourMin: '{n} h {m} min',
durHours: '{n} h',
durDay: '1 day',
durDays: '{n} days',
},
netshare: {
noOnchain: 'no on-chain asset',
zero: 'No bitcoin in view yet, every sat is a start.',
tier: { shrimp: 'Shrimp', crab: 'Crab', octopus: 'Octopus', fish: 'Fish', dolphin: 'Dolphin', shark: 'Shark', whale: 'Whale', humpback: 'Humpback' },
quotesUnder: [
'I officially own **{X} billionths** of all the Bitcoin that will ever exist. My savings account can pack up and go.',
'**{X} billionths** of the Bitcoin universe are mine. Scientifically a speck of dust, emotionally a fortune.',
'With my share of **{X} billionths** I own a tiny piece of the future of money. Give it a while and it buys me a cheese sandwich.',
'Share of the Bitcoin network: **{X} billionths**. Share of my ego about it: 100%.',
'Technically I am now a Bitcoin stakeholder. Practically I own **{X} billionths** of a pizza purchase from 2010.',
'I own **{X} billionths** of all Bitcoin. A small start, and a big story to brag about.',
'Statistically negligible, emotionally priceless: **{X} billionths** of 21 million coins.',
'I own a fraction so small my calculator rounds it away, but my wallet app does not. **{X} billionths**, and nobody takes that from me.',
'Split all Bitcoin into a billion pieces and I hold **{X}** of them. Split it further and I am still proud.',
'My share of the network is **{X} billionths**. My share of the hype around it: considerably bigger.',
'**{X} billionths** of Bitcoin are mine. Enough to brag about, too little to buy anything with.',
'I co-own **{X} billionths** of digital gold. The rest of the gold, sadly, belongs to someone else.',
'Nano investor reporting: **{X} billionths** of the total supply, and proud as a peacock.',
'Small share, big story: **{X} billionths** of all Bitcoin ever.',
'I have less Bitcoin than there are stars visible to the naked eye, but I do own **{X} billionths** of the network. Progress is progress.',
],
quotesOver: [
'I own a **whole number** of Bitcoin. In a world of decimals I am a whole coin. And people may know it.',
'Holding **{Y}** of the network, I can officially say: I have a piece of the 21 million. Not a crumb, a bite.',
'1 BTC or more: the moment your wallet app starts taking you seriously.',
'My share: **{Y}**. Small on the scale of the universe, big on the scale of my friends without Bitcoin.',
'I am past the magic line of 1 BTC. I can keep saying so for the rest of my life.',
'**{Y}** of all the Bitcoin that will ever exist is mine. That number never grows again. My pride does.',
'From "billionths" to "a whole coin", an upgrade no smartphone can match.',
'Share of the network: **{Y}**. Share of telling this fact at parties: 100%.',
'I no longer have to say "not even 1 BTC". I just say "1 BTC". A short sentence, a big feeling.',
'**{Y}** of Bitcoin is mine. Scarce, finite, and forever a good conversation starter.',
'From shrimp to something bigger on the Bitcoin ladder. My wallet is evolving.',
'I own **{Y}** of an asset that will never exceed 21 million. Rarer than my patience for explaining this at birthday parties.',
],
},
sysmetrics: {
db: 'Database',
calls: 'Calls',
errors: 'Errors',
window: 'window',
},
range: {
cycle: 'Other period',
pointCarried: '{bron}, price of {dag}',
pointVia: '{name} ({source})',
day: 'D',
week: 'W',
month: 'M',
year: 'Y',
all: 'A',
},
spot: {
noHistory: 'no history',
unknownAsset: 'unknown asset',
},
filter: {
all: 'All',
none: 'None',
},
actions: {
title: 'To do',
interestTitle: 'Interest to record',
valuationTitle: 'Valuation differences',
openTitle: 'Still to do',
openOne: 'item open',
openMany: 'items open',
openNone: 'Nothing open',
},
appWindow: {
close: 'Close',
confirmTitle: 'Close app',
confirmClose: 'Close the app and this window? Reopen it with start-app.',
closeUnavailable: 'Closing is only possible on this computer, in the window the app opened itself.',
},
guide: {
title: 'Help',
goTo: 'Go to {plek}',
related: 'See also',
newTab: 'Opens in a new tab',
figures: {
period: 'Selected period',
sinceBuy: 'Unrealized and Invested: since the purchase',
inPeriod: 'Return, Gain/loss, Realized',
purchase: 'Purchase',
yearStart: 'January 1',
now: 'Now',
cost: 'Cost basis 191.20',
broughtIn: 'Contributed (net) 154.92',
value: 'Now: 186.43',
unrealized: 'Unrealized -4.77',
result: 'Gain/loss',
resultAmount: '31.51',
purchaseExchange: 'Purchase (exchange)',
transfer: 'Transfer',
legendValue: 'Value',
legendBroughtIn: 'Contributed (net)',
legendCost: 'Cost basis of the asset',
roughly: 'is roughly',
unrealizedPart: 'Unrealized',
realized: 'Realized',
interest: 'Interest',
},
},
aiProposals: {
title: 'Proposals from the AI connection',
intro: 'The AI connection proposed this. Nothing has changed yet; the app carries it out only when '
+ 'you approve.',
kindPricePoint: 'Record price',
kindAccount: 'New account',
kindAccountDelete: 'Delete account',
kindValuation: 'Balance',
kindPortfolio: 'New portfolio',
portfolioIn: 'in',
portfolioNote: 'Empty, and without API keys or data from these records. It is not opened: '
+ 'you switch yourself on System → Portfolios, and that restarts the app.',
kindPreference: 'Change setting',
preferenceNote: 'This setting applies to this portfolio and only changes the display or '
+ 'an interval, not the records themselves.',
preferenceCurrent: 'now',
preferenceOn: 'on',
preferenceOff: 'off',
kindSourceChoice: 'Source choice',
sourceFirst: 'first',
sourceRemove: 'remove',
sourceChoiceNote: 'You can see the chain as it stands now on Integrations, Source choice, or on the Source tab of Price history.',
unknownKind: 'Unknown kind of proposal',
ledger: 'ledger',
diff: 'difference',
openingBalance: 'This becomes an OPENING BALANCE: there is no entry before this date, so the app '
+ 'will show no difference after it. Check the balance extra carefully.',
irreversible: 'Irreversible. Not included in "Approve all".',
acceptDelete: 'Delete',
acceptDeleteConfirm: 'Permanently delete this account? This cannot be undone. '
+ 'If it has entries, balances or scans, the app refuses.',
bulkSkips: '{n} proposal(s) delete something and are skipped by "Approve all". '
+ 'You approve those separately.',
bulkNothing: 'Nothing open can be approved in one go. What is there deletes '
+ 'something and needs a separate confirmation.',
ownCustody: 'self-custody',
thirdParty: 'with a third party',
fee: 'fees',
perUnit: 'per',
accept: 'Approve',
reject: 'Reject',
acceptAll: 'Approve all',
rejectAll: 'Reject all',
acceptAllConfirm: 'Approve and carry out {n} proposals?',
rejectAllConfirm: 'Reject {n} proposals? They disappear from this list and are not carried out.',
rejectedByUser: 'Rejected on To do',
failed: 'Previous attempt failed',
partialTitle: 'Not everything succeeded',
partialBody: 'The rest was handled. These remain:',
unknownProposal: 'Proposal {id} no longer exists.',
handled_accepted: 'Proposal {id} has already been approved.',
handled_rejected: 'Proposal {id} has already been rejected.',
unreadableMoment: 'Unreadable moment in proposal {id}: {moment}.',
prefScopeNotAllowed: 'This proposal wants to change the settings under "{scope}", and that is not allowed.',
duplicateValuation: 'There is already a balance for this account and this asset on {dag}.',
noPriceForBalance: 'No price in the history for {dag}, and a balance cannot do without one. First '
+ 'propose a price point on that date (propose_price_point), then this balance can be recorded after it.',
},
reservations: {
title: 'Reservations',
hint: 'A reservation is an amount that may be debited or credited later. It counts nowhere '
+ 'until you record it; from its date it appears on To do. You can add one on the Reservations tab and in the account window.',
none: 'No reservations on this account.',
noneAll: 'No reservations yet.',
colDate: 'Date',
colAccount: 'Account',
colDirection: 'Direction',
colAsset: 'Asset',
colAmount: 'Amount',
colNote: 'Description',
dirOut: 'Debit',
dirIn: 'Credit',
due: 'Date reached',
book: 'Record',
settle: 'Without entry',
bookTitle: 'Record reservation',
otherTo: 'To',
otherFrom: 'From',
outside: 'Outside the portfolio',
fill: 'Enter a date, an asset and an amount greater than zero.',
confirmSettle: 'Settle this reservation without an entry? It then disappears.',
confirmDelete: 'Delete this reservation?',
notOpen: 'This reservation is no longer open.',
cardOne: '1 reservation',
cardMany: '{n} reservations',
cardNext: 'next {datum}',
},
notify: {
title: 'Notifications',
none: 'Nothing to do.',
dismiss: 'Hide',
reconcile: 'Movements to reconcile',
interest: 'Interest to record',
valuation: 'Valuation differences',
schedule_ended: 'Interest schedule ended',
source_proposal: 'Confirm price source',
ai_proposal: 'AI proposal',
reservation: 'Reservation to settle',
view: 'View',
hint: {
reconcile: 'Unlinked on-chain movements',
interest: 'Credits ready to record',
valuation: 'Balance differs from the valuation',
source_proposal: 'Proposed price source for a new asset',
ai_proposal: 'Proposed by the AI connection, awaiting your approval',
reservation: 'The date of a reservation has been reached: record it or settle it without an entry',
},
},
integrationLog: {
title: 'Error log',
open: 'Error log',
openHint: 'The failed calls of the past {n} days',
lastFailure: 'Last error',
noFailures: 'No errors in the past {n} days.',
allSources: 'All sources',
service: 'Atreides Services',
colTime: 'Time',
colSource: 'Source',
colOperation: 'Call',
colSubject: 'Subject',
colOutcome: 'Outcome',
colStatus: 'Status',
colKey: 'Key',
colDetail: 'Details',
colRequestId: 'Request ID',
requestIdHint: 'The same ID is in the Atreides Services log.',
outcome_fail: 'Failed',
outcome_empty: 'Empty response',
outcome_refused: 'Not sent',
},
integrations: {
matrixPaid: 'The source choice matrix is part of the paid version. The app keeps using the default sources.',
keysPaid: 'Your own provider API keys are part of the paid version; the default sources keep working.',
title: 'Integrations',
intro: 'External integrations and their endpoints. For each integration you manage the API keys, see the status and test the connection.',
indicatorHint: 'API activity, click for integrations and metrics',
baseUrlOrProfile: 'Base URL / profile',
endpoints: 'Endpoints',
coverage: 'Coverage',
noCoverage: 'No covering source: record the coverage on an integration.',
systemSource: 'System source: {naam}. There is nothing to choose here.',
convertedVia: 'converted to {munt} via {naam}, the source choice of {valuta}',
sourcesHintTitle: 'Source choice',
coverageUsage: 'Coverage and source choice',
coverageUnchosen: 'covered, but not chosen anywhere',
inactiveNoEffect: 'This integration is off: the source choice has no effect until you turn it on.',
inactiveHint: 'gray: the integration is off, so this choice does nothing until you turn it on',
noRateSource: 'no exchange rate source for {valuta}',
noRateSourceHint: 'This source quotes in {valuta}. First choose a source for the exchange rate of {valuta}, then you can choose it here.',
method: 'Method',
path: 'Path',
auth: 'Authentication type',
authYes: 'Requires API key',
authNo: 'Public',
authKind: {
none: 'Public',
header_key: 'API key in a header',
query_key: 'API key in the URL',
bearer: 'Bearer token',
basic: 'Username and password',
hmac: 'Signed request (HMAC)',
},
authHeaderName: 'Header name',
authParameterName: 'URL parameter name',
keys: 'API keys',
keysSet: 'Set',
keysMissing: 'Not set',
keysNone: 'No API keys needed',
testFail: 'Failed',
noBackend: 'backend unreachable',
saved: 'Saved',
keysTitle: 'API keys',
keysHint: 'API keys are stored server-side; the browser never sees them. Leave a field empty to keep it unchanged.',
keysEmpty: 'Not set',
saveKeys: 'Save API keys',
api_key: 'API key',
api_secret: 'API secret',
capability: 'Type',
query: 'Query',
symbol: 'Symbol',
date: 'Date',
active: 'Active',
authRequired: 'API key required',
authOptional: 'API key optional',
authKeyStored: 'API key stored',
autoActivated: 'Integration activated (test passed)',
symbolsTitle: 'Input mapping',
outputsTitle: 'Output mapping',
hmacTitle: 'HMAC signing',
authTitle: 'Authentication',
keyRequiredCol: 'API key required',
kinds: 'Types',
yes: 'Yes',
no: 'No',
saveAuth: 'Save authentication',
readonlyNote: 'Configuration is read-only in this version.',
testMapTitle: 'Test & map',
runTest: 'Test & map',
testRunning: 'Working…',
mappedResult: 'Mapping result',
rawResponse: 'Raw response',
metricsTitle: 'Metrics',
calls: 'calls',
okCount: 'succeeded',
failCount: 'failed',
avgLatency: 'avg.',
maxLatency: 'max',
noMetrics: 'no calls',
period_uur: 'Last hour',
period_dag: 'Today',
period_maand: 'This month',
subtabMapping: 'Fields & mapping',
subtabAuth: 'Auth & API keys',
subtabTest: 'Test',
subtabMetrics: 'Metrics',
subtabUsage: 'Source choice',
usageNoCoverage: 'This source does not cover any asset yet: record the coverage in the row.',
quoteCurrency: 'Currency',
chartCalls: 'Calls (succeeded / failed)',
chartLatency: 'Latency (max, ms)',
deleteProvider: 'Delete',
cap: { spot: 'Spot', daily_history: 'Daily history', history_point: 'Historical point' },
tabProviders: 'Providers',
tabSources: 'Source choice',
tabConnections: 'Connections',
sourcesSoon: 'The source choice matrix (which integration supplies which data, per asset and capability) will have its place here. We build it as the next step; until then you manage the source per asset on the Assets page.',
newProvider: 'New integration',
name: 'Name',
field: 'Field',
transform: 'Transform',
externalId: 'External ID',
addEndpoint: 'Add endpoint',
addSymbol: 'Add symbol',
addOutput: 'Add output',
confirmDeleteProvider: 'Delete this integration and all its configuration?',
confirmDeleteRow: 'Delete this row?',
hmacMessageParts: 'Message parts',
hmacHashAlgo: 'Hash algorithm',
hmacEncoding: 'Encoding',
hmacKeyHeader: 'Key header',
hmacSignatureHeader: 'Signature header',
hmacTimestampHeader: 'Timestamp header',
hmacWindowHeader: 'Window header',
hmacWindowMs: 'Window (ms)',
saveHmac: 'Save HMAC',
clearHmac: 'Clear HMAC',
hmacNone: 'No HMAC signing configured.',
systemNote: 'System provider, not editable.',
asset: 'Asset',
nameRequired: 'An integration needs a name.',
keyInUse: 'An integration with the key "{key}" already exists.',
unknownProvider: 'Integration "{key}" does not exist.',
providerInMatrix: 'Integration "{key}" is still in the source matrix ({n} choice(s)); remove those first under Source choice.',
providerHasPrices: 'Integration "{key}" still has {n} price row(s) in the history; they still need it as their source.',
fieldRequired: '{veld} is required.',
priceCallFailed: 'Price call failed ({status}).',
price: {
externalIdMissing: 'The output path uses {external_id}, but there is no external ID.',
listPathWithoutBrackets: 'List path without []: "{pad}".',
expectedArray: 'Expected an array at "{pad}".',
expectedObject: 'Expected an object at "{pad}".',
unknownTransform: 'Unknown transform: "{transform}".',
noOutputMapping: 'Provider {provider}: no output mapping for "{capability}".',
noValidPrice: 'Provider {provider}: no valid price in the response.',
limitReached: '{provider}: the monthly limit of {limiet} calls has been reached; no more requests go out this month.',
noExchangeRate: 'No exchange rate for {valuta} on or shortly before {datum}; without an exchange rate there is no price in {munt}.',
invalidDate: 'Provider {provider}: invalid date "{datum}".',
columnsUneven: 'Provider {provider}: the output columns differ in length.',
capabilityNotConfigured: 'Provider {provider}: capability "{capability}" is not configured.',
symbolMissing: 'Provider {provider}: {external_id} is used but no symbol was given.',
templateDateInvalid: 'Provider {provider}: the template uses {date}, but date "{datum}" is invalid.',
unknownHmacToken: 'Unknown hmac message token: "{token}".',
unknownCapability: 'Unknown capability: "{capability}".',
onlyGet: 'Provider {provider}: only GET is supported.',
unknownAuthKind: 'Unknown authenticationKind: "{soort}".',
keyMissing: 'Provider {provider}: an API key is required but is missing or incomplete.',
parameterNameMissing: 'Provider {provider}: the URL parameter name is missing (API key in the URL).',
headerNameMissing: 'Provider {provider}: the header name is missing (API key in a header).',
hmacConfigMissing: 'Provider {provider}: the hmac configuration is missing.',
networkError: 'Provider {provider} {capability}: network error ({reden}).',
httpFailed: 'Provider {provider} {capability} failed ({status}){detail}.',
notJson: 'Provider {provider} {capability}: the response is not JSON ({detail}).',
notFromFixedRate: 'Provider {provider}: "{capability}" cannot come from a fixed rate.',
callFailed: '{label} failed ({status}).',
callTimeout: '{label} timed out (timeout {s}s).',
labelAddress: 'Fetching address {adres}',
labelAddressTxs: 'Fetching transactions for {adres}',
labelAddressTxsPage: 'Transactions (page)',
},
scriptLoadFailed: 'Failed to load script: {src}',
unknownEndpoint: 'Endpoint {id} does not exist.',
quoteCurrencyInvalid: 'Quote currency "{waarde}" is not a three-letter currency code.',
minIntervalInvalid: 'Interval "{waarde}" is not a whole number of seconds above zero.',
quoteUnit: 'Unit',
quoteUnitNone: 'as stored',
quoteUnitOpt: { ozt: 'per troy ounce' },
quoteUnitInvalid: 'Unknown unit "{waarde}".',
minInterval: 'Interval (s)',
minIntervalApp: 'default',
intervalHours: '{n} h',
intervalMinutes: '{n} min',
intervalSeconds: '{n} s',
callLimitInvalid: 'A monthly limit is a whole number above zero, not "{waarde}".',
usageCol: 'Usage (month)',
callLimitCol: 'Monthly limit',
usageHint: 'Calls this calendar month, succeeded and failed together, against the monthly limit of the subscription. The test button does not count.',
unknownSymbolMap: 'Input mapping {id} does not exist.',
catchAll: 'All others',
catchAllHint: 'Applies to every symbol without its own rule. The Symbol field then stays empty.',
catchAllSymbol: 'all others',
catchAllExists: 'This source already has a rule for all other symbols.',
unknownOutputMap: 'Output mapping {id} does not exist.',
matrixHint: 'For each asset you choose a source for the spot price and one for the history; that choice applies everywhere in the app. Clicking an empty cell makes it the next choice (1, then 2 as backup); clicking a chosen cell removes it. A yellow ring is a proposal that a click confirms; an empty cell without a plus is something the source does not supply. History covers a series and a price per date: the app fetches the series if there is one, and per date whatever is missing. By default only assets with more than one source are shown; you turn on the rest in the filter.',
sourceCap: { spot: 'Spot', history: 'History' },
mxToSetUp: '{wat} still to set up',
mxOpenOne: '1 choice still open',
mxOpenMany: '{n} choices still open',
mxAllChosen: 'all chosen',
mxServiceHint_first: 'Atreides Services: after a source you selected yourself and before the sources the app chose. Select a source to put it before the service. The setting is on System → Integrations → Connections.',
mxServiceHint_fallback: 'Atreides Services: as a fallback, after all chosen sources. The setting is on System → Integrations → Connections.',
mxProposalsOne: '1 proposal',
mxProposalsMany: '{n} proposals',
},
table: { none: 'Ungrouped', new: 'New', save: 'Save', cancel: 'Cancel', search: 'Search…', count: 'Number of records', edit: 'Edit' },
action: { copy: 'Copy' },
dialog: { ok: 'OK', cancel: 'Cancel', close: 'Close', error: 'Something went wrong',
next: 'Next', back: 'Back', finish: 'Finish', skip: 'Skip' },
setup: {
currencyTitle: 'Which currency is your bank account in?',
accountsTitle: 'Where is it held?',
account_wallet: 'Own wallet',
account_exchange: 'Exchange',
account_bank: 'Bank',
dashboardTitle: 'On the dashboard',
widget_standing: 'Current position',
widget_spot: 'Prices',
finish: 'Set up',
persona_bitcoin: 'Bitcoin only',
persona_broad: 'Broader',
rerun: 'Set up…',
},
notes: {
tab: 'Notes',
when: 'Date and time of the line',
line: 'New line, Enter adds it at the top',
body: 'Notes on this asset. Freely editable; they also appear in the other detail window of this asset.',
saving: 'Saving…',
saved: 'Saved',
},
error: { panelTitle: 'Something went wrong loading this section', panelHint: 'The rest of the app keeps working. Details below (also in the console).' },
blur: { toggle: 'Hide/show amounts', showAmounts: 'Show amounts' },
controls: { theme: 'Theme', accent: 'Accent', currency: 'Currency', dark: 'Dark', light: 'Light', orange: 'Orange', lila: 'Lilac', blue: 'Blue', teal: 'Teal', magenta: 'Magenta', indigo: 'Indigo', cyan: 'Cyan', slate: 'Slate', sand: 'Sand', flat: 'Flat', deep: 'Relief', business: 'Business', glass: 'Glass' },
settings: {
prefBadValue: 'Invalid value for {scope}.{key}: {waarde}.',
prefWantsInteger: 'Invalid value for {scope}.{key}: {waarde} (an integer was expected).',
prefBelowMin: '{scope}.{key} cannot be less than {min}.',
prefAboveMax: '{scope}.{key} cannot be greater than {max}.',
unknownSetting: 'Unknown setting: {key}.',
title: 'Settings',
appearance: 'Appearance',
screen: 'Screen',
region: 'Region',
profile: 'Profile',
theme: 'Theme',
accent: 'Accent color',
depth: 'Depth',
depthHint: 'Relief gives the page an accent glow and frames with shadow and edge light; Flat keeps everything plain. Business only.',
glowBg: 'Background glow',
glowBgMotion: 'Background glow and animation',
glowOff: 'Off',
glowOn: 'On',
glowStill: 'Still',
glowStep: 'Occasionally',
glowAlways: 'Always',
glowShape: 'Glow shape',
glowShapeBlobs: 'Orbs',
glowShapeBands: 'Beams',
rowsel: 'Selected table row',
rowselLight: 'Edge light',
rowselTint: 'Tint',
rowselPill: 'Pill',
glass: 'Glass',
glassTransparency: 'Transparency',
glassFrost: 'Frost',
glassDialog: 'Dialog transparency',
glassDefault: 'Default',
glassRender: 'Glass rendering',
glassRenderMimic: 'Simulated',
glassRenderReal: 'Real blur',
motionBlocked: 'Your system asks for reduced motion, so the glow stands still.',
transparencyBlocked: 'Your system asks for reduced transparency, so the glass is opaque.',
hintTitle: 'Settings',
hintProfile: 'Profile: Business is flat and fast, Glass adds a glow behind and translucent frames over it.',
hintTheme: 'Theme and accent color apply in both profiles; the accent color also tints the glow.',
hintGlow: 'Background glow and animation: in Glass, three orbs in the accent color. With Occasionally one shifts now and then; Always moves continuously and takes the most processing.',
hintGlowShape: 'Glow shape, only in Glass with the glow on: Orbs (default) are three spots that shift; Beams are broad light beams in three layers that fall slowly from the top right corner, over the still glow. With Occasionally that comes in showers: light for a while, then nothing for a while.',
hintRowsel: 'Selected table row, only in Glass: Edge light comes from the stripe on the left, Tint colors the whole row, Pill turns it into a rounded strip.',
hintAiHeading: 'Only through the AI',
hintAiIntro: 'This is not on the page. Ask the AI assistant to change it; the proposal appears on To do.',
hintAiTempo: 'Glow tempo: Brisk, Calm (default) or Very calm.',
hintGlassRender: 'Glass rendering, only in Glass: Simulated (default) is faster, Real blur blurs what lies behind the cards and takes more processing.',
hintGlass: 'Glass, only in Glass: Transparency applies to cards and frames (default 65%), Frost to all glass (3%), Dialog transparency to what floats above the content, such as a dialog, menu or tooltip (30%): 0 is opaque, 100 fully transparent, and the more transparent, the less blurred. A table header does not blur. Default resets them, and Glass rendering to Simulated.',
hintScreenHeading: 'Screen',
autoBlur: 'Hide amounts after',
autoBlurHint: 'Time without activity before the amounts blur. With "Manual" you toggle it yourself with the eye icon.',
autoBlurManual: 'Manual',
minutesShort: 'min',
assetDisplay: 'Asset display',
assetDisplayHint: 'Show the name, the symbol, or both. At least one stays on.',
pageTitle: 'Page title',
pageTitleShow: 'Show',
pageTitleHide: 'Hide',
pageTitleHint: 'The title above each page. When hidden, the content starts higher; the page name is also in the menu.',
pageHint: 'Page legend',
pageHintHint: 'The i icon in the margin, with the explanation of what you see on that page. When hidden, the icon disappears entirely; a page without a legend never shows it.',
resultSigns: 'Sign on gains and losses',
resultSignsNone: 'None',
resultSignsNegative: 'Negative only',
resultSignsBoth: 'Negative and positive',
resultSignsHint: 'Applies to gains/losses and returns in green or red. With "None" only the color says whether it is a gain or a loss. Without color the sign is always shown.',
persona: 'Portfolio covers',
personaHint: 'Broader hides Signals & Charts and the bitcoin widgets from the dashboard choice. Per portfolio; entries and assets do not change.',
kiosk: 'Open in',
kioskWindow: 'Browser',
kioskFull: 'Own window',
kioskHint: 'Own window opens the app at the next start with start-app in its own window without address bar and tabs, maximized (Vivaldi, Edge or Chrome). Without one of those browsers the app opens in a regular tab. F11 makes it full screen; moving it to another screen works as with any window. Under System you then find Close, which closes the app and the window. On a server or the Umbrel this choice has no effect.',
language: 'Language',
nl: 'Nederlands',
en: 'English',
},
ai: {
notConnected: 'No AI assistant has been connected yet. As soon as that happens, this shows '
+ 'per call what was done and which data left the app.',
howTo: 'You connect with your own AI program on this computer. That program starts the '
+ 'connection itself; no web address and no password are needed.',
total: 'Calls',
lastAt: 'Last call',
ok: 'Completed',
error: 'Failed',
refused: 'Refused',
when: 'When',
what: 'What',
who: 'By',
shared: 'Data shared',
characters: 'Characters',
result: 'Outcome',
sharedNothing: 'nothing',
sharedUnknown: 'not recorded',
sharedSome: 'some data',
unknownClient: 'unknown program',
detailNone: '',
noRows: 'No calls match the filters.',
conversation: 'The conversation',
msgRequest: 'Received',
msgResponse: 'Answered',
noConversation: 'The text of this call was not saved. It was handled by a version '
+ 'of the app that did not yet record the conversation.',
conversationFail: 'The conversation could not be loaded.',
switchOn: 'On: a connected AI program may make calls.',
switchOff: 'Off: every call is refused, including from an AI program that is already running.',
switchFail: 'Saving the setting failed.',
activeHead: 'Active',
switchHead: 'Read',
writeHead: 'Write',
controlHead: 'Navigation',
rawHead: 'Raw',
activeOn: 'On: the connection works. What an AI may do is set by the switches next to it.',
activeOff: 'Off: no connection is running. The connection test does nothing either and a running '
+ 'AI program stops itself.',
writeOn: 'On: an AI may add or change data, always through a proposal that you approve.',
writeOff: 'Off: every request to change something is refused.',
rawLabel: 'Share raw',
rawOn: 'On: an AI sees the real names and amounts of this portfolio.',
rawOff: 'Off: an AI sees references and ranges instead of names and amounts.',
rawHint: 'Only turn this on if this portfolio contains no real data. The app cannot '
+ 'determine that; only you know. Note: a copy of a portfolio contains the data of '
+ 'the original.',
rawConfirm: 'Turn on raw sharing for "{naam}"? A connected AI then sees the real names '
+ 'and amounts of this portfolio instead of references and ranges. Only do this if there is '
+ 'no real data in it.',
precisionTitle: 'How precisely an AI sees the numbers',
precisionIntro: 'On means ranges instead of exact numbers, and that is how the '
+ 'app has always worked. Turn one off and that kind comes through exactly. If "Raw" is on, '
+ 'these four do nothing: there is nothing to make a range of.',
sharesHead: 'Percentages',
sharesOn: 'On: the distribution across your assets comes in ranges, for example "20 to 25%".',
sharesOff: 'Off: the distribution comes exactly, for example "23.4%".',
totalsHead: 'Totals',
totalsOn: 'On: the total of your net worth comes as a range.',
totalsOff: 'Off: the total comes as an exact amount.',
amountsHead: 'Amounts',
amountsOn: 'On: an amount in a row comes as a range.',
amountsOff: 'Off: an amount in a row comes exactly.',
quantitiesHead: 'Quantities',
quantitiesOn: 'On: a quantity (0.05 BTC) comes as a range.',
quantitiesOff: 'Off: a quantity comes exactly.',
precisionCombo: 'Note: if "Percentages" and "Totals" are both off, an AI answer leaves out the '
+ 'distribution across your assets. Together those two pin down the value per asset, while the '
+ 'amounts per row are in ranges.',
scope: 'These settings apply only to the portfolio that is open now: {naam}.',
revoke: 'A right you grant can always be revoked here: turn the switch off and it applies '
+ 'from the next call, also for an AI program that is already running. No restart is needed. '
+ 'What has already been approved stays; revoking is about what an AI may do from now on.',
controlLabel: 'The app may be controlled',
controlHint: 'This lets an AI take you to a page. Your data is not '
+ 'read or changed by it. You see every jump coming and can stop it.',
controlOn: 'On: an AI may take you to a page.',
controlOff: 'Off: a request to navigate is refused.',
connectTitle: 'Connect to your AI program',
connectIntro: 'Put the lines below in the configuration file of your AI program. The path is already '
+ 'filled in for this computer. Hover over the box and click the copy button at the top right; then paste '
+ 'the block unchanged into that file.',
connectFile: 'In Claude Desktop that file is called claude_desktop_config.json. If there is already a '
+ '"mcpServers" block, add only the lines inside it.',
connectRestart: 'The AI program must then be restarted; only then does it read the '
+ 'new configuration.',
connectCopy: 'Copy',
connectCopied: 'Copied',
connectCopyFail: 'Copying failed. Select the text above and copy with Ctrl+C.',
connectFail: 'The connection details could not be fetched.',
dryTitle: 'Preview what would be shared',
dryIntro: 'Choose an action and see exactly what an AI program would get to see. The '
+ 'action really runs on your data, but the answer goes to this screen and '
+ 'not outside. Nothing is changed and no row is added to the log below, '
+ 'because nothing was sent.',
dryPick: 'Action',
dryRun: 'Preview',
dryBusy: 'Working…',
dryFail: 'The preview failed.',
dryResult: 'This is what the AI program would get to see',
dryScope: {
none: 'does not touch your records',
read: 'reads your records',
write: 'changes data',
control: 'controls the app, reads no data',
},
dryArgs: 'Values for this action',
dryArgRequired: 'required',
dryArgPick: 'Choose…',
dryNeedsArg: 'Fill in the required values first.',
dryArgHandleNone: 'You get a reference from another action. First preview "Overzicht van de '
+ 'inrichting"; its output contains references such as account:7f3a9c that you can enter here.',
dryArgHandleSome: 'Choose a reference you saw earlier, or type one in from a conversation.',
},
home: {
title: 'Dashboard',
assets: 'Assets',
locations: 'Locations',
events: 'Events',
valuations: 'Reference date values',
accounts: 'Accounts',
reconcile: 'Reconcile',
rematch: 'Update',
updating: 'Updating',
rematchDone: 'new links made',
rematchNone: 'No new links: everything is already linked.',
recAsTrade: 'Buy/Sell',
recAsTransfer: 'Transfer',
recIgnore: 'Ignore',
recTotal: 'Amount paid ({munt})',
recPrice: 'Fill price per unit ({munt})',
recPriceLoading: 'Fetching price…',
recPriceFrom: 'Daily price of {date} from the price history, per {unit}. You can change it.',
recPriceAt: 'Price at {time} from Atreides Services, per {unit}. You can change it.',
recPriceUnknown: 'No price known for that date. Enter the price yourself, or 0 if you paid nothing '
+ 'for it.',
recPriceRequired: 'Enter a price.',
recTxAt: 'Time of the transaction',
recDetectedAt: 'The transaction is not confirmed yet; this is the time the app saw it',
recCounter: 'Counter account',
recConfirm: 'Confirm',
recIn: 'received',
recOut: 'sent',
recLightning: 'Lightning',
recVia: 'via {wallet}',
recViaNwc: 'NWC wallet',
recDone: 'Processed.',
records: 'records',
recPending: 'Open differences',
recHandled: 'Handled',
recHandledNone: 'Nothing handled yet.',
recRevert: 'Revert',
recRevertConfirm: 'Revert this proposal? Any event created for it will be deleted.',
recLink: 'Link to event',
recDelete: 'Delete',
recDeleteConfirm: 'Delete this proposal from the list? Any event or link created for it stays.',
recUnknownProposal: 'Proposal {id} no longer exists.',
recHandled_accepted_trade: 'Proposal {id} is already recorded as a purchase or sale.',
recHandled_accepted_transfer: 'Proposal {id} is already recorded as a transfer.',
recHandled_accepted_interest: 'Proposal {id} is already recorded as interest.',
recHandled_ignored: 'Proposal {id} is already ignored.',
recHandled_auto_linked: 'Proposal {id} is already linked automatically.',
recNoCounter: 'There is no counter account to record to. Set a second account to active first.',
recAsInternal: 'Within the account',
recAsChannelTransfer: 'To the channel on {account}',
recInternal_channel: 'channel opened or closed',
recInternal_self: 'payment to yourself',
recInternalHint: 'Stays within the account: only the fee is deducted.',
recNotInternal: 'Proposal {id} is not a movement within the account.',
recBookAll: 'Record Lightning ({n})',
recBookAllConfirm: 'Record {trade} lightning payments as a purchase or sale, at the price of the '
+ 'moment or else the daily price, {internal} movements within the account and {interest} forwards as '
+ 'interest. {skipped} regular on-chain movements stay; you record those one by one.',
recAsInterest: 'As interest',
recInterestHint: 'Routing income from your node: counts as income, not as a deposit.',
recNotForward: 'Proposal {id} is not a lightning forward.',
recBookAllProgress: 'Recording {i} of {n}',
recBookAllDoneTitle: 'Lightning recorded',
recBookAllDone: '{booked} recorded. Left open without a price: {noPrice}. Failed: {failed}.',
recAutoLinked: 'Proposal {id} was linked automatically; to unlink it, use "Link to event".',
recStillOpen: 'Proposal {id} is still open; there is nothing to revert.',
recPrev: 'Previous',
recNext: 'Next',
recAll: 'All proposals',
recIgnoreAll: 'Ignore all',
recDeleteAll: 'Delete all',
recIgnoreAllConfirm: 'Ignore all open proposals? Ignored proposals do not come back on a rescan.',
recDeleteAllConfirm: 'Delete all open proposals? The handled log stays; unlinked movements reappear on a new scan.',
btcWidget: 'Bitcoin',
toSignals: 'To Signals & Charts',
hintTitle: 'Arranging the dashboard',
hintEdit: 'Press and hold a widget to customize the layout.',
hintDone: 'Done: Escape, a click beside the widgets or another page.',
hintAdd: 'Add: point at an empty spot and click the +. On a phone the list is below the widgets.',
hintWidget: 'Move a widget by its handle; the button next to it opens its settings.',
hintProfiles: 'Choose a layout in the menu. Deleting Default starts over with the default layout.',
groupAccount: 'By account',
groupAccountKind: 'By account type',
groupAsset: 'By asset',
groupAssetKind: 'By asset type',
groupBy: 'Group',
standing: 'Current position',
toWealth: 'To Wealth',
standingNone: 'No positions yet. Book a purchase or record a balance.',
showToday: 'Show return',
},
conversion: {
title: 'Bitcoin Conversions',
btcRate: 'Bitcoin price',
loading: 'Fetching price…',
updatedAt: 'Updated at',
rateUnavailable: 'Price not available',
fiat: 'Euro',
fiatHint: 'Traditional currency',
btcHint: 'Base unit · max 21 million',
hierarchy: 'Unit hierarchy',
satNote: 'The satoshi is the smallest on-chain unit. The millisatoshi exists only on the Lightning Network.',
footer: 'Live price from the selected price source',
},
labels: {
title: 'Labels',
inUse: 'Label is used by {n} item(s); unlink those first.',
new: 'New label',
edit: 'Edit',
cancel: 'Cancel',
save: 'Save',
name: 'Name',
color: 'Color',
useColor: 'Use color',
none: 'No labels yet.',
delete: 'Delete',
confirmDelete: 'Delete this label?',
colColor: 'Color',
colName: 'Name',
badHex: 'Invalid color. Use e.g. #39FF8A.',
},
accounts: {
maxFreeBank: 'The free version is limited to {max} fiat bank account. A license removes that limit; '
+ 'nothing is removed in the meantime.',
title: 'Accounts',
nameRequired: 'Enter a name.',
new: 'New account',
edit: 'Edit',
cancel: 'Cancel',
save: 'Save',
name: 'Name',
kind: 'Type',
ownCustody: 'Self-custody',
scanEnabled: 'Scan automatically',
taxCategory: 'Category',
taxCategoryAuto: 'follows asset',
taxScope: 'Taxes',
taxScopeAuto: 'default (follows asset)',
wealthScope: 'Wealth',
wealthScopeAuto: 'default (own wealth)',
color: 'Color',
useColor: 'Use color',
label: 'Label',
none: 'No accounts yet.',
confirmDelete: 'Delete this account?',
yes: 'Yes',
no: 'No',
sources: 'Tracking sources',
sourcesFor: 'Tracking sources of',
addSource: 'Add tracking source',
sourceKind: 'Type',
sourceValue: 'Value',
xpub: 'xpub / ypub / zpub',
address: 'Single address',
nwc: 'NWC (Nostr Wallet Connect)',
lnd: 'LND (Lightning node)',
noSources: 'No tracking sources for this account yet.',
noSourceKind: 'This account type has no tracking source.',
interestManageHint: 'Add and change them on',
interestNone: 'No interest schedules for this account yet.',
interestMovedLink: 'Interest & Rewards',
merge: 'Merge',
mergeTitle: 'Merge two accounts into one',
mergeNeedTwo: 'You need at least two accounts to merge.',
mergePick: '(choose an account)',
mergeKeep: 'Account to keep',
mergeDrop: 'Account to remove',
mergeSummary: '"{drop}" → "{keep}". Moves: {sources} source(s), {events} event(s), {schedules} schedule(s), {valuations} valuation(s).',
mergeConfirm: 'This merge cannot be undone. Continue? (Run a rescan afterwards.)',
mergeDone: 'Accounts merged. Run a rescan to refresh the tracking cache.',
mergeReason_pickTwo: 'Choose two accounts.',
mergeReason_sameAccount: 'Choose two different accounts.',
mergeReason_notFound: 'Account not found.',
mergeReason_sourceMismatch: 'Not possible: one type has tracking sources and the other does not (e.g. exchange × wallet).',
mergeReason_kindCannotCarry: 'Not possible: the account to keep cannot carry the source types of the other. Choose the Lightning account as the account to keep, or set it to type "Lightning" first.',
sourceValueRequired: 'Enter an xpub, address or NWC URI.',
sourceNameRequired: 'Give the tracking source a name.',
inUse: 'This account is used by {n} entry(ies); delete or relink those first.',
unknownAccount: 'Account #{id} does not exist.',
sourceUriMissing: 'The NWC URI is missing.',
sourceNotLnd: 'The selected connection is not an LND connection.',
labelNoTxs: 'No movements were given for the label.',
sourceNamePh: 'e.g. Ledger receiving',
colSourceName: 'Name',
confirmDeleteSource: 'Delete this tracking source and its scanned addresses?',
testSource: 'Test',
testing: 'Testing…',
testValid: 'valid',
testTxs: 'transactions',
testFail: 'Test failed',
nwcPubkey: 'wallet pubkey',
nwcKeepPh: 'URI saved: leave empty to keep, paste a new one to replace',
colSourceKind: 'Type',
colSourceValue: 'Source',
colConnection: 'Connection',
colScriptType: 'Type',
lndVia: 'via',
lndHeight: 'block height',
lndNoConnection: 'Choose an LND connection (create one first under Connections).',
noNode: 'None',
onchainOfNode: 'on-chain of',
onchainOfNodeHint: 'This wallet is the on-chain side of that node. A channel it opens is recorded by the app as a transfer to the node account.',
'script_p2tr': 'Taproot (bc1p…)',
'script_p2wpkh': 'Native SegWit (zpub · bc1q…)',
'script_p2sh-p2wpkh': 'Nested SegWit (ypub · 3…)',
'script_p2pkh': 'Legacy (xpub · 1…)',
interest: 'Interest received',
intDate: 'Date',
intAsset: 'Asset',
intAmount: 'Amount',
intValue: 'Value',
noInterest: 'No interest received on this account yet.',
schedules: 'Interest schedules',
schPrincipalAsset: 'Locked',
schPrincipal: 'Principal',
schRate: 'Interest',
schPayoutAsset: 'Payout',
schStart: 'Start',
schEnd: 'End',
schCadence: 'Credit',
schWeekday: 'Weekday',
schDayOfMonth: 'Day of month',
wd0: 'Sunday', wd1: 'Monday', wd2: 'Tuesday', wd3: 'Wednesday', wd4: 'Thursday', wd5: 'Friday', wd6: 'Saturday',
schRateType: 'Type',
schNote: 'Note',
noSchedules: 'No interest schedules for this account yet.',
confirmDeleteSchedule: 'Delete this interest schedule?',
schAssetRequired: 'Choose the locked asset.',
schPayoutRequired: 'Choose a payout asset.',
schRateInvalid: 'Enter a valid interest rate.',
schStartRequired: 'Enter a start date.',
schEndBeforeStart: 'The end date is before the start date.',
projection: 'Forecast',
projectionHint: 'Remaining credits, for information only, not counted in balance or taxes.',
projReceived: 'Received',
projExpectRemain: 'Still expected',
projCount: '{n} credits',
projTermTotal: 'Total for the term',
projEndBalance: 'Final balance {datum}',
projEndBalanceSub: 'deposit plus interest',
projNext: 'Next',
projAllUpcoming: 'All {n} upcoming credits',
projOver: 'on {bedrag}',
projUntil: 'through {datum}',
dueTitle: 'Interest to record',
book: 'Record',
dismiss: 'Ignore',
bookOldestFirst: 'Record from oldest to newest: each credit raises the balance the next one is calculated on. Ignoring is allowed in any order and releases the next one.',
confirmBook: 'Credit interest:',
},
interest: {
title: 'Interest & Rewards',
none: 'No interest events yet.',
needAsset: 'Add an asset first.',
colDate: 'Date',
time: 'Time',
colAccount: 'Account',
colAsset: 'Asset',
colAmount: 'Amount',
colSource: 'Source',
colNote: 'Note',
colSchedule: 'Interest schedule',
noSchedule: 'No schedule',
new: 'New interest',
save: 'Save',
cancel: 'Cancel',
confirmDelete: 'Delete this interest event?',
confirmDeletePeriod: 'Delete this rate period?',
invalid: 'Enter date, account, asset and amount (> 0).',
importNote: 'Imported records are authoritative and cannot be edited.',
schedulesTitle: 'Interest schedules',
recordsTitle: 'Interest received',
principalFollowsBalance: 'follows the balance',
endsOnOpen: 'ongoing',
cadenceNone: 'No credit cycle',
colCompounding: 'Compound interest',
compoundingViaBalance: 'via the balance',
depositTitle: 'Principal empty',
depositWarning: 'This schedule has an end date and follows the balance, and the interest is paid to this account. Then each credit is also calculated on interest recorded earlier. For a term deposit the bank usually calculates on the starting amount: enter that as the principal.',
depositSaveAnyway: 'Save anyway',
depositBack: 'Enter principal',
depositNotSaved: 'Not saved: enter the starting amount as the principal, or save and choose Save anyway.',
periods: 'Rate periods',
periodsBase: 'From the start of the schedule on',
periodsVariable: 'This schedule is set to "manual or import": the app calculates nothing here, so there are no rate periods.',
periodStartsOn: 'Starts on',
periodRateRequired: 'Enter an interest rate.',
noPeriods: 'No changes yet; the rate of the schedule applies for the whole term.',
noSchedules: 'No interest schedules yet. Add one to see forecasts and interest to record.',
schAccountRequired: 'Choose an account for the schedule.',
principalPositive: 'The principal must be greater than 0. Leave the field empty to follow the account balance.',
rateNotNegative: 'The annual interest rate cannot be negative.',
compoundingNeedsPrincipal: 'Compound interest requires a fixed principal. A principal that follows the balance already grows with each recorded credit.',
compoundingNeedsSameAsset: 'Compound interest is only possible if the interest is paid in the same asset as the principal.',
weekdayRequired: 'Choose a weekday for the weekly credit.',
dayOfMonthRequired: 'Choose a day of the month for the monthly credit.',
unknownSchedule: 'This interest schedule does not exist.',
unknownPeriod: 'This rate period does not exist.',
periodStartRequired: 'Enter an effective date.',
periodStartBeforeSchedule: 'The effective date must be after the start of the schedule ({start}); the rate from that day is in the schedule itself.',
bookOlderFirst: 'First record the credit for {start} → {eind}. Each credit raises the '
+ 'balance the next one is calculated on, so the order determines the amount.',
periodStartAfterEnd: 'The effective date is after the end of the schedule ({eind}).',
},
taxes: {
title: 'Taxes',
loading: 'Calculating…',
empty: 'Nothing to calculate yet.',
emptyWhy: 'Add an event (a purchase or a transfer) or set a balance; from then on this page calculates the reference dates.',
colAccount: 'Account',
colAsset: 'Asset',
groupAccount: 'By account',
groupAsset: 'By asset',
groupKind: 'By type',
colKind: 'Type',
catTitle: 'Category',
catBank: 'Bank balances',
catOverig: 'Other assets',
catUnknown: 'No category',
catNote: 'Category: the amounts split into bank balances and other assets. Appears as soon as a category is chosen on an account or asset, or "Listed separately only" under Taxes (System, tabs Assets and Accounts). Without a choice an asset follows its type: currency is a bank balance, the rest is another asset. What appears only here does not count in the table and the gain/loss; money to and from such an account counts there as a deposit or withdrawal.',
showAll: 'Show all',
showAllTip: 'Show the page as if Category and Taxes on Assets and Accounts are set to the default everywhere.',
showAllNote: 'Show all: if an asset or account has something other than the default under Category or Taxes, this switch shows the page as if everything is set to the default. That way you see what those choices change. The switch setting is remembered.',
colCurrent: 'Current value',
total: 'Total',
untilNow: '· to date',
hintTitle: 'What you see here',
hintMainTitle: 'Value per reference date',
mainNote: 'Value per reference date (January 1, 00:00) in the base currency: the position at that moment × the price of that day. The position is the last recorded balance plus the events after it, or Σ events if there is no balance.',
pctNote: 'Hover over an amount to see the return for the period ending at that column; the January 1 column therefore covers the year before it. The total row does show the percentage, as that is the figure for the whole.',
pctMwr: 'MWR',
pctIrr: 'IRR',
pctMwrTip: 'Money-weighted return using Modified Dietz: what YOUR money did, divided by the average invested capital (each deposit counts in proportion to how long it was in). End value minus start value, minus what you bought or transferred to this account, plus what went out, and minus what came from a balance instead of an entry. Buying more therefore does not count as profit. Empty if there was no start value to measure against.',
pctIrrTip: 'Money-weighted return using the internal rate of return (IRR), annualized: the rate that exactly explains your deposits and withdrawals. Where it does not exist (a position that drops to zero in between) the figure falls back to Modified Dietz. Adjustable in the display settings.',
aangifteTitle: 'Gain/loss',
colPeriod: 'Jan 1 {van} → Jan 1 {tot}',
colPeriodNow: 'Jan 1 {van} → now',
cellReturn: '{label} {pct}, gain/loss {bedrag}',
cellResult: 'Gain/loss {bedrag}',
buitenBox3: 'Kept out of the overview (does count as net worth):',
emptyColsNote: 'Reference dates left out because nothing was there: {jaren}. In the gain/loss per year they '
+ 'remain the start value of that year.',
startYearNote: 'These records start in {eerste} and are shown from reference date January 1 {start}. The positions include everything before that; only columns are missing. The start year is set under System → Portfolios.',
aangifteNote: 'Key figures per year for the net worth in this app: crypto, precious metals and the accounts you track here. Return = end value - start value - purchases + sales - what came from balances. "Current value" is the current year to date; a year gets its own column once it is complete. The header of a year column is the reference date on which that year ends, so the columns line up with the table above: the End value here is the same reference date column there, and the Start value is the column to its right. Click an amount to copy it (rounded to whole units). This app does not calculate tax: these are the key figures a tax return usually asks for; rates and exemptions differ per country.',
kgRendement: 'Return',
kgUitBalansen: 'From balances (not recorded)',
kgGiften: 'Gifts (nothing paid)',
kgUnexplained: 'Of which unexplained',
kgUnexplainedTip: 'Part of the change comes from a measured balance and not from entries. If that was a deposit you did not record, the return is that much lower; if it was income, this amount is correct.',
zonderKoersTip: 'Left out of this return because the price is missing on one of the two reference dates: {namen}. Counting it as zero would read that missing price as a loss or gain. Add the price under Price history, or fill in the value with a balance.',
zonderKoersWhere: 'Left out of the return because the price is missing on one of the two reference dates:',
unexplainedWhere: 'Of which unexplained, per account (a negative amount means the entries explain more than the position changed, usually a jump from an earlier year that you have now recorded):',
unexplainedOpeningAll: 'an opening balance with no entries before it, so there is nothing to record here',
unexplainedOpening: 'of which from an opening balance with no entries before it:',
owrBegin: 'Start value',
owrEind: 'End value',
owrDeposits: 'Purchases (deposits)',
owrWithdrawals: 'Sales (withdrawals)',
},
eventAccounts: {
none: 'No accounts yet.',
noneWhy: 'A balance belongs to an account. Create one first.',
manage: 'Manage accounts',
empty: 'No balance',
closed: 'Closed',
openGaps: '{n} difference(s) to check',
open: 'Open account',
pickAsset: 'Show only this asset in the tables; click again for all',
showEmpty: 'Without balance',
recordBalance: 'Record balance',
recordBalanceHint: 'Record the current balance as a balance entry. Change the amount if your statement says otherwise; the difference then goes to To do.',
recordBalanceTitle: 'Record the {asset} balance as a balance entry',
lastBalance: 'Balance {datum}',
fromBookings: 'From entries',
noPrice: 'no price',
hintTitle: 'Accounts',
hintBalance: 'The balance is the latest recorded balance plus the entries after it, the same number as on Wealth. "Balance" is the date of that latest recorded balance; "From entries" means no balance has been recorded for this asset yet.',
hintDetail: 'Click a card to see and edit the balances, buys and sells, transfers and interest of that account. Click an asset there to filter the tables on that asset.',
interestAgreement: 'Interest schedule',
interestAgreements: '{n} interest schedules',
interestBooked: '{n}× interest recorded, last {datum}',
interestNext: 'expected {datum}: {bedrag}',
nowTotal: 'now {bedrag} on the accounts shown',
nowTotalPartial: 'now {bedrag} on the accounts shown, excluding assets without a price',
act: {
buy: 'buy',
sell: 'sell',
transferIn: 'transfer in',
transferOut: 'transfer out',
interest: 'interest',
balance: 'balance recorded',
agreementStart: 'interest schedule starts',
agreementEnd: 'interest schedule ends',
accountOpened: 'account created',
accountClosed: 'account closed',
accountChanged: 'account last changed',
reservation: 'reservation',
interestDue: 'interest expected',
},
hintActivity: 'The line at the top (all accounts shown), at the bottom of a card and in the account window is the activity from the start year of the portfolio: a peak up is a day on which something came in, a dip a day on which something went out; the height follows the number of entries. Ticks are balances, interest schedules, expected interest payments, reservations (a small square) and changes to the account; the line runs to the last of these, even if it lies in the future. In the account window, clicking a day opens that entry or reservation.',
hintInterest: 'Below the balance: the current interest schedules of the account and how often interest or rewards were recorded.',
hintCapture: 'The "Record balance" button is shown by default only for money. Turn it on or off per asset under System, tab Assets, column "Record balance".',
},
valuations: {
maxFree: 'The free version is limited to {max} balance. A license removes that limit; nothing is removed in the meantime.',
title: 'Balances',
needAsset: 'Create an asset first or migrate the data on the overview.',
colDate: 'Reference date',
colTime: 'Time',
colUpdated: 'Updated',
colAccount: 'Account',
colAsset: 'Asset',
colBalance: 'Balance',
colRate: 'Price ({munt})',
colSource: 'Source',
colDiff: 'Difference',
ratePlaceholder: 'empty = look up',
rateNote: 'Leave the price empty = looked up automatically at the reference date and time, via the source chosen for this asset. A balance is the anchor for the position of that account: the position is this balance plus the events after it. If there are also events before the reference moment, Difference shows whether they match, and "Record" writes the difference as one correction at the price of that moment.',
anchorHint: 'This is the anchor for the position of this account: there are no events before this reference moment, so there is nothing to reconcile.',
futureHint: 'This reference date is still to come. The balance does not count in your position yet and creates no work; once the reference moment has passed, it becomes the anchor for this account.',
book: 'Record',
accept: 'Accept',
acceptHint: 'This difference is not income but money that went in or out. No entry, and it no longer counts as unexplained.',
confirmAccept: 'Accept this difference? It then counts as money going in or out of your records, not as return. You can undo this later.',
lightningRow: 'Measured at Update',
lightningHint: 'The balance on Tracking (on-chain plus lightning) against what your records said at that moment.',
recordBalance: 'Record as balance',
recordBalanceHint: 'The measured balance becomes a balance on that day. After that it is listed here as a regular balance, with Record and Accept.',
recordTitle: 'Record measured balance',
recordRate: 'Price on {date}',
lightningSameDay: 'There is already a balance on {date} for this account; it will not be overwritten.',
acceptedMark: '✓ accepted',
acceptedHint: 'Accepted difference, click to undo:',
bookTitle: 'Record difference',
bookAsSuffix: 'record as',
bookAsSell: 'Sell (left your portfolio)',
bookAsBuy: 'Buy (entered your portfolio)',
bookAsTransferTo: 'Transfer to',
bookAsTransferFrom: 'Transfer from',
bookAsFeeOn: 'Fees on {soort} of {datum}',
bookReplaces: 'existing line becomes',
bookRemoves: 'removes the existing line',
bookNote: 'valuation correction',
bookFeeNote: 'fees added via Record difference',
invalid: 'Fill in reference date, asset and balance (≥ 0).',
noRate: 'No price found for this time.',
none: 'No balances yet.',
confirmDelete: 'Delete this balance?',
},
assets: {
title: 'Assets',
decimalsRange: 'Decimals must be a whole number from 0 to {max} (received: "{waarde}"). Above that, a quantity can no longer be read back.',
inUse: 'Asset is in use by {n} record(s); delete those first.',
maxFree: 'The free version is limited to {max} asset. A license removes that limit; nothing is removed in the meantime.',
freeOnly: 'The free version tracks {list} and currencies only. A license removes that limit.',
fillSymbolNameUnit: 'Fill in symbol, name and main unit.',
metalUnitUnknown: 'Metal main unit must be a known unit: {eenheden}.',
fillDecimals: 'Fill in decimals (≥ 0).',
new: 'New asset',
edit: 'Edit',
cancel: 'Cancel',
save: 'Save',
symbol: 'Symbol',
name: 'Name',
kind: 'Type',
unit: 'Main unit',
subunit: 'Subunit',
displayUnit: 'Display',
decimals: 'Decimals',
taxCategory: 'Category',
taxCategoryAuto: 'follows type',
taxCategoryAutoIs: 'follows type ({waarde})',
taxScope: 'Taxes',
taxScopeAuto: 'default (counts)',
balanceCapture: 'Record balance',
balanceCaptureOn: 'On',
balanceCaptureOff: 'Off',
balanceCaptureAutoOn: 'follows type (on)',
balanceCaptureAutoOff: 'follows type (off)',
priceSource: 'Price source',
none: 'No assets yet.',
delete: 'Delete',
confirmDelete: 'Delete this asset?',
},
metalProducts: {
title: 'Coins & bars',
assetRequired: 'Choose a valid metal asset.',
nameRequired: 'The name is required.',
fineGramsPositive: 'The fine weight must be greater than 0.',
pickMetalAndName: 'Choose a metal and fill in a name.',
fillFineGrams: 'Fill in a valid fine weight (> 0).',
notMetal: 'The selected asset is not a metal.',
inUse: 'This product is in use by {n} event(s); delete those first.',
asset: 'Metal',
name: 'Name',
form: 'Form',
fineWeight: 'Fine weight',
weight: 'Weight',
unit: 'Unit',
save: 'Save',
cancel: 'Cancel',
none: 'No coins or bars yet.',
needMetal: 'Add a metal asset first (Master data → Assets).',
confirmDelete: 'Delete this product?',
},
wealth: {
title: 'Wealth',
none: 'No assets with a position yet.',
quantity: 'Quantity',
value: 'Current value',
avgSpot: 'Avg. purchase price',
avgPremium: 'Avg. premium/event',
unrealized: 'Unrealized',
realized: 'Realized',
share: 'Share of total',
result: 'Gain/loss',
twr: 'Return',
twrTotal: 'Return',
unexplained: 'Unexplained',
allYears: 'All',
noPrice: 'No price known for this period: no value, share or return.',
yearPick: 'Choose a year or a range of years',
yearRangeTip: 'Shift+click for a range of years.',
yearOff: 'Click to leave out this year and everything before it',
legendTitle: 'What you see here',
legendSparkValue: 'Value of the position per day.',
legendSparkInvested: 'Invested. The difference with the solid line is the gain/loss.',
legendBuy: 'Buy.',
legendSell: 'Sell. A jump without a dot comes from the market.',
legendRings: 'Distribution over types (left) and assets (right) as a share of total net worth; below 2% goes into "Other".',
legendUnexplained: 'Unexplained: a balance differs from the entries on that account, so an entry is missing. Accounts tracked by balance only do not count. Does not count as return.',
legendTwr: 'Return is time-weighted: only the price counts, not deposits or timing ("Unrealized" does count those). Interest, staking and cashback count as holdings on receipt and are included in "Gain/loss". The base currency has no return. The money-weighted return is on Taxes.',
legendRange: 'Year selection: calendar years, the current year up to today. Shift-click selects a range; deselecting a selected year also drops the years before it. Everything on the page follows the selection, with amounts at the end of the period (the following January 1). Every asset that moved in the period gets a card, even if it has since been sold. The detail window always shows "All".',
legendInvested: 'Invested: price paid plus premium and fees. "Avg. purchase price", "Avg. premium/event" and "Invested" per asset are in the detail window; the purchase price measures only the spot price.',
legendResult: 'Gain/loss: what the position yielded in the selected period, the change in value minus the net amount invested. Price gains, sales and interest count. Unrealized applies since purchase and only to what you still hold; over all years, gain/loss is roughly unrealized plus realized plus interest.',
legendDetail: '"Show details": the chart at full size, with accounts and entries. Pointing at a row highlights that day in the chart.',
legendChain: 'Return over multiple years is chained, not added: two years of +10% is +21% combined. A year box shows that year on its own.',
legendNoPrice: '"No price known": the quantity comes from the entries; value, share, gain/loss and return stay empty (not zero). Return counts from the first known price. You can add price points via a source on Price history or via the AI connection; one per year is enough.',
legendUnrealized: 'Unrealized: against the price paid including fees and premium. Realized: proceeds of sales in the period minus fees and cost basis. A dash: nothing sold or cost basis unknown. A coin stands at minus the premium until the spot price earns it back; loose weight has no product.',
invested: 'Invested',
total: 'Total value',
product: 'Product',
form: 'Form',
count: 'Count',
weight: 'Weight',
unallocated: 'Unallocated / loose weight',
openDetail: 'Show details',
tradesTitle: 'Buys and sells',
tradeDate: 'Date',
tradeType: 'Type',
tradeBuy: 'Buy',
tradeSell: 'Sell',
tradePrice: 'Price',
tradeAmount: 'Amount',
noTrades: 'No buys or sells on this account.',
noChart: 'No history over the selected period.',
ringKinds: 'By type',
ringAssets: 'By asset',
ringKindsLabel: 'Distribution of your net worth over the asset types',
ringAssetsLabel: 'Distribution of your net worth over the individual assets',
ringOther: 'Other',
perAccount: 'By account',
sinceStart: 'Since start',
openYearOverview: 'Open annual net worth overview',
openReturn: 'Open return',
returnTitle: 'Return',
returnDay: 'This day',
returnSoFar: 'Since start of period',
returnCarried: 'No price on this day: the previous one is carried forward, so the movement only shows at the next price.',
periodDay: '1 day',
periodDays: '{n} days',
periodYear: '1 year',
returnData: 'Based on',
returnTotal: 'Total net worth',
returnSelection: 'Selection ({n} assets)',
returnKinds: 'Type',
returnAssets: 'Asset',
perAsset: 'By asset',
groupBy: 'Group the cards',
asset: 'Asset',
shareOfAccount: 'Share of account',
broughtInNet: 'Contributed (net)',
ownWealth: 'Own wealth',
othersWealth: 'Third-party wealth',
costOnArrival: 'Cost basis on arrival',
account: 'Account',
noAccountAssets: 'This account holds nothing right now.',
legendAccounts: 'By account: the same prices as by asset. Unrealized in proportion to the units, with the average cost basis of own wealth. A third-party account has its own cost basis: the daily price at which it came in, plus what it bought itself. A transfer between your own accounts counts for the return as a withdrawal and a deposit at the daily price, so only the price and the fees count. The second line is what was brought in, transfers included, and the gain/loss is the difference with the value. Whatever is on no account gets the card "No account".',
legendFilter: 'Filter: turning off a card only hides the card. The total, the rings and the return still include it. By account you filter by type, such as exchange or wallet.',
showAllTip: 'Also show the wealth you manage for someone else and what does not count on Wealth.',
legendShowAll: 'Show all (the switch at the total): if an account is set to "Third-party wealth" or "Not counted" under Wealth (System, tab Accounts), that page does not count the account. Money to and from such an account counts as a withdrawal or deposit, not as gain/loss. The switch shows everything, and its setting is remembered.',
legendManaged: 'Third-party wealth, not counted: {bedrag}.',
legendNotCounted: 'Not counted, excluded: {bedrag}.',
legendShowAllOn: 'Show all is on: third-party wealth and what does not count are included in the figures. In the window of an asset, third-party wealth is on its own tab, with its own key figures.',
yearOverviewTitle: 'Annual net worth overview',
valueEnd: 'Value at end',
investedNet: 'Invested (net)',
noLongerHeld: 'No longer held',
noLongerHeldSince: 'Since {dag} the quantity is zero. The card is shown because you still held this asset in this period; return and gain/loss cover that time.',
year: 'Year',
noYears: 'No years to show yet.',
perProduct: 'By product',
noAccount: 'No account',
noAccountRows: 'No position per account to show.',
},
transfers: {
title: 'Transfers',
fillDateAsset: 'Enter date and asset.',
pickValidProduct: 'Choose a valid product.',
fillCount: 'Enter a number of pieces (> 0).',
fillDateAssetQuantity: 'Enter date, asset and quantity (> 0).',
fillOneAccount: 'Enter at least one from/to account.',
fillThisAccount: 'Choose this account as the from or to account.',
new: 'New transfer',
edit: 'Edit',
cancel: 'Cancel',
save: 'Save',
colOrigin: 'Origin',
originPick: 'Regular transfer',
originNone: 'Nothing in return',
originNonePick: 'Nothing in return: received or a bonus',
asset: 'Asset',
date: 'Date',
time: 'Time',
amount: 'Quantity (sats)',
from: 'From',
to: 'To',
unitFee: 'Fee (sats, on-chain)',
note: 'Note',
none: 'No transfers yet.',
delete: 'Delete',
confirmDelete: 'Delete this transfer?',
needAsset: 'Create an asset first or migrate the data on the overview.',
colDate: 'Date',
colAsset: 'Asset',
colAmount: 'Quantity',
colFrom: 'From',
colTo: 'To',
colDirection: 'Direction',
colOther: 'From / to',
dirIn: 'In',
dirOut: 'Out',
colFee: 'Fee',
colNote: 'Note',
colAddress: 'On-chain address',
colSource: 'Source',
addressPlaceholder: 'On-chain receiving address (for auto-match)',
colKind: 'Type',
colProduct: 'Product',
addCrypto: 'Transfer crypto',
addMetal: 'Transfer precious metal',
addFiat: 'Transfer money',
looseWeight: '(loose weight)',
internal: 'internal',
fiatNote: 'Fiat value = market price (nearest) on the transfer date, in the base currency.',
matched: 'Also found in on-chain tracking',
},
trades: {
title: 'Buy & Sell',
noSpotForDate: 'No price found for this date. Enter the price yourself, or 0 if you paid nothing for it.',
saveCancelled: 'Save canceled: adjust the price.',
fillDateAssetPrice: 'Enter date, asset and price.',
pickValidProduct: 'Choose a valid product.',
fillCount: 'Enter a number of pieces (> 0).',
fillQuantity: 'Enter a quantity (> 0).',
new: 'New trade',
edit: 'Edit',
cancel: 'Cancel',
save: 'Save',
type: 'Type',
asset: 'Asset',
date: 'Date',
time: 'Time',
amount: 'Quantity (sats)',
location: 'Location',
note: 'Note',
none: 'No trades yet.',
delete: 'Delete',
confirmDelete: 'Delete this trade?',
needAsset: 'Create an asset first or migrate the data on the overview.',
colDate: 'Date',
colType: 'Type',
colAsset: 'Asset',
colAmount: 'Quantity',
colTotal: 'Amount',
colPrice: 'Price/unit',
colOrigin: 'Origin',
originUnknown: 'Unknown',
originPaidHint: 'The price comes from you: an amount or a price per unit that you entered.',
originMarketDay: 'Daily price, looked up by the app. The time of the entry is not taken into account.',
originMarketMoment: 'Price at the time of the entry, looked up by the app.',
originNoneHint: 'Received without anything in return, so a gift. The price is 0, and that is the correct answer here.',
originUnknownHint: 'This entry predates the app recording this; whether the price was paid or looked up is unknown.',
originPick: 'Unknown, or let the app choose',
originPickPaid: 'Paid: this number comes from me',
originPickGift: 'Gift: nothing paid',
colSource: 'Source',
colFee: 'Fee',
feeOnInterest: 'Fees on interest are not counted anywhere, so this entry is not saved. Remove the fees or lower the amount.',
unitFeeOnBuy: 'Fees in the asset itself on a purchase are not counted anywhere. Record the amount you received, without those fees, or enter the fees in fiat.',
colAccount: 'Account',
colNote: 'Note',
colKind: 'Type',
colProduct: 'Product',
addCrypto: 'Add crypto',
addMetal: 'Add precious metal',
addFiat: 'Deposit or withdraw money',
looseWeight: '(loose weight)',
fiatNote: 'Amount = quantity × price per unit, including the fee on a buy and after deducting the fee on a sell.',
matched: 'Also found in on-chain tracking',
},
priceOrigin: {
price: 'Price {prijs} on {dag}',
pricePer: 'Price {prijs} per {eenheid} on {dag}',
someSource: 'a source',
close: 'Closing price from {bron}',
manual: 'Entered manually',
live: 'Current price, still moving',
liveFrom: 'Current price from {bron}, still moving',
spot: 'Derived from a spot price from {bron}, not a closing price',
spotAt: 'Derived from the {tijd} spot price at {bron}, not a closing price',
devBefore: '{pct} off the previous closing price',
devAfter: '{pct} off the next one',
carried: 'Carried forward from {dag} ({bron}), {n} days old',
strength: 'Accuracy: {sterkte}',
sumHead: 'Based on {n} prices',
sumWeakest: 'Weakest: {asset}, {zin}',
sumMissing: 'No price for {assets}: counts as zero',
pageWarnTitle: 'Missing prices',
pageWarn: 'On this page, at least one amount is missing a price: that item counts as zero. Hover over the amounts; where it applies, a yellow i shows which item it is.',
bookingPrice: 'Price {prijs}',
bookingPricePer: 'Price {prijs} per {eenheid}',
bookingPaid: 'Paid: the price you entered yourself',
bookingMoment: 'The price at the time of the entry',
bookingDay: 'Daily price of {dag}, looked up when recording',
bookingDayFrom: 'Daily price of {dag}: {zin}',
bookingDayNote: 'A daily price is not the price of the exact moment',
bookingUnknown: 'Not recorded whether this price was paid or looked up',
strength_unknown: 'unknown',
strength_high: 'high',
strength_lower: 'lower',
strength_low: 'low',
strength_missing: 'incomplete',
},
priceHistory: {
title: 'Price history',
confirmDeletePoint: 'Delete this price?',
gapsMore: 'And {n} more gaps; fill these first.',
gapLine: '{van} to {tot}, {n} days',
gapFill: 'Fill',
gapNoSource: 'No source is selected for {asset} that provides a series or a price per date. Choose one under Integrations, Source choice.',
gapConfirmPoint: 'This requests up to {n} prices from {bron}, one request per day. A source with a monthly limit can run through that quickly.',
gapConfirmSeries: 'This fetches the series from {reeks} (at most once a day).',
gapConfirmBoth: 'This first fetches the series from {reeks}, then requests what is still missing from {bron} per day: up to {n} requests.',
gapFillAll: 'Fill all',
gapIgnore: 'Ignore',
gapUnignore: 'Count again',
gapIgnoreAll: 'Ignore all',
gapIgnoreAllConfirm: 'These {n} gaps will no longer be shown and no longer count toward the indicator dot. You can restore them under Ignored, at the bottom of this tab.',
gapNone: 'No open gaps.',
gapBusy: 'Filling…',
gapIgnoreConfirm: 'This gap will no longer be shown and no longer counts toward the indicator dot. Use this for days that no source has. You can restore it under Ignored.',
gapCountOne: '{n} gap',
gapCountMany: '{n} gaps',
dayCountOne: '{n} day',
dayCountMany: '{n} days',
suspectOne: '{n} suspicious price',
suspectMany: '{n} suspicious prices',
gapCardSummary: '{gaten}, {dagen}',
gapStop: 'Stop',
gapStopProgress: 'Stop ({i} of {n})',
gapStopped: 'Filling stopped; the rest was not requested.',
gapLimit: 'The monthly limit of the source has been reached, so filling stopped. What is still missing can be filled next month, or through another source for this type.',
gapFilled: '{asset}: the gaps are filled.',
gapRemaining: '{asset}: {n} days still without a price.',
gapWhySeries: '{reeks} provides a series that only starts on {begin}, and no active source fetches a price per date (such as GoldAPI). For the days before that, you can ignore the gap or enter prices manually; enabling a per-date source costs one request per day.',
gapWhySeriesHole: 'These days fall within the series from {reeks}, but that source has no prices for them itself: a gap in its data. A source that fetches a price per date (such as GoldAPI) can fill them, for {n} requests; otherwise ignore them or enter them manually.',
gapWhySeriesEmpty: '{reeks} returned nothing for these days, and no active source fetches a price per date (such as GoldAPI). Ignore the gap or enter prices manually.',
gapWhyPoint: '{bron} returned no price for these days: a weekend or holiday, a date before its history, or the monthly limit is used up.',
kind_close: 'closing price',
kind_manual: 'manual',
kind_live: 'today',
kind_spot: 'derived',
kind_carried: 'carried forward',
kind_none: 'no price',
kindCount: '{n} {soort}',
kindCount_closeOne: 'closing price',
kindCount_closeMany: 'closing prices',
kindCount_manualOne: 'manual',
kindCount_manualMany: 'manual',
kindCount_liveOne: 'today',
kindCount_liveMany: 'today',
kindCount_spotOne: 'derived',
kindCount_spotMany: 'derived',
kindCount_carriedOne: 'carried forward',
kindCount_carriedMany: 'carried forward',
kindCount_noneOne: 'without a price',
kindCount_noneMany: 'without a price',
cardPeriod: '{dagen}:',
cardNoPrices: 'No prices yet.',
stripDay: '{dag}: {soort}',
stripRange: '{van} to {tot}: {soort}',
cardGaps: '{gaten}, {dagen} without a price',
tabProvenance: 'Origin',
tabGaps: 'Gaps',
tabIgnored: 'Ignored',
tabAbsent: 'No price at source',
absentExplain: 'The source returned no price for these days, so the app does not request them again. Remove a line to have those days requested again at the next fill.',
absentLine: '{bron}: {van} to {tot}, {dagen}',
absentLineOne: '{bron}: {dag}',
absentForget: 'Request again',
tabPrices: 'Prices',
tabCheck: 'Check',
checkFactor: 'factor {n}',
checkShare: '{n}%',
checkHint: 'Delete or correct a wrong row under Prices. If a price is correct after all, you can accept the finding at System, Health.',
checkShowKind: 'Show in Prices',
checkOpenRow: 'Show this price in Prices',
checkFiltered: 'Filtered on Check: {soort} ({n}).',
checkFilteredDay: 'Filtered on {dag}, from Check.',
checkClearFilter: 'All prices',
tipMoment: 'price at {tijd}',
tipDeviation: '{voor} off the previous closing price, {na} off the next one',
provNoWeak: 'Every day in this period has a closing price.',
provRange: '{van} to {tot}',
provColPeriod: 'Period',
provColKind: 'Kind',
provColDays: 'Days',
provColNote: 'Details',
provColSource: 'Source',
provToGaps: 'Go to this gap under Gaps',
provSpotNote: 'up to {pct} off the closing price',
provCarriedNote: 'up to {n} days old',
tabSource: 'Source',
diagCard_noCoverage: 'No integration provides prices',
diagCard_allInactive: '{namen} is turned off',
diagCard_noChoice: 'No source selected',
diagCard_choiceUnusable: 'Source choice does not work',
diagCard_limitReached: 'Monthly limit reached: {namen}',
diagCard_choiceInactive: 'Selected but turned off: {namen}',
diag_noCoverage: 'No integration provides a series or a price per date for {symbool}. Add one under Integrations, or enter prices manually.',
diag_allInactive: '{namen} provides prices for {symbool}, but is turned off. Turn it on under Integrations.',
diag_noChoice: 'No source is selected for the price history of {symbool}, so no prices come in.',
diag_choiceUnusable: 'The selected source ({namen}) is turned off or provides no prices for {symbool}, so no prices come in.',
diag_limitReached: 'The monthly limit of {namen} has been reached. No new prices for {symbool} will come in this month.',
diag_limitReachedFallback: 'The monthly limit of {namen} has been reached. The next source in the chain takes over.',
diag_choiceInactive: 'Selected but turned off: {namen}. The next source in the chain takes over; choose another one under Integrations, Source choice, or turn it on.',
diagProposal: 'Proposal: {naam} for the price history.',
momentTitle: 'Price at a specific moment',
date: 'Date',
time: 'Time',
useTime: 'Use time',
peildatum: 'Reference date',
lookup: 'Fetch price',
loading: 'Fetching price…',
requested: 'Requested',
actual: 'Actual price point',
diff: 'difference',
histTitle: 'Stored price history (database)',
startDate: 'From date',
histLookup: 'Show',
sync: 'Sync with mempool',
syncing: 'Syncing…',
synced: 'price points stored',
storedEmpty: 'No stored history yet. Click "Sync with mempool" to fetch and store the price history.',
points: 'stored points',
noPoints: 'No stored price points on or after this date.',
colUnit: 'Per',
manualUnknownAsset: 'That asset does not exist (anymore).',
manualBadMoment: 'Enter a valid date.',
manualFutureMoment: 'A price cannot be in the future.',
manualBadPrice: 'A price must be a number above zero.',
colDateTime: 'Date & time',
colDate: 'Date',
colTime: 'Time',
colCombined: 'Integration · Asset · Price',
search: 'Search…',
assetLabel: 'Asset',
compare: 'Compare integrations',
comparing: 'Querying integrations…',
cmpDayTitle: 'Day resolution (daily figures)',
cmpDayNote: 'Daily figures for the selected date, comparable with each other.',
cmpTsTitle: 'Timestamp resolution (spot now)',
cmpTsNote: 'Live spot price per integration (current moment): not comparable with daily figures.',
cmpNone: 'No integration returned a price for this asset.',
colDiff: 'Difference',
colResolution: 'Resolution',
colIntegration: 'Integration',
colAsset: 'Asset',
resDay: 'day',
resTimestamp: 'timestamp',
tableTitle: 'All stored price points',
colUpdated: 'Updated',
allAssets: 'All assets',
refresh: 'Refresh',
delete: 'Delete',
noAsset: 'Choose an asset.',
noDate: 'Enter a date.',
lookupNone: 'No price point found, and fetching from the source returned nothing.',
dayCovers: 'Daily figure: applies to the whole day (no exact time).',
peilTitle: 'Reference date prices',
peilBody: 'Fetch the price for the configured reference date',
peilFetch: 'Fetch reference date prices (all assets)',
peilNoneForAsset: 'no price found',
resTitle: 'About the resolution',
resBody: 'This page uses the mempool API. The historical-price endpoint returns the nearest stored price point, not the exact requested time. For older data, that can differ by hours up to a day; the actual time of the returned point is therefore shown with the result. An exact price to the minute requires an exchange OHLC API (spot_api phase).',
},
tracking: {
title: 'Tracking',
zapFrom: 'Zap from {who}',
zapTo: 'Zap to {who}',
zapIn: 'Zap received',
zapOut: 'Zap sent',
noAccountsWithSources: 'No accounts with a tracking source yet.',
manageAccounts: 'Manage accounts',
selectAccount: 'Account',
accountTotal: 'Total balance',
sourceFallback: 'Tracking source',
badgeNwc: 'Wallet pubkey',
badgeNwcHint: 'An NWC wallet, identified by its wallet pubkey (Nostr Wallet Connect)',
badgeLnd: 'Lightning node',
badgeLndHint: 'An LND node, connected on the Connections tab',
walletOne: 'wallet',
walletMany: 'wallets',
statWallets: 'Wallets',
statTxs: 'Transactions',
statLinked: 'Linked',
selectedSum: 'Selected:',
selectedOf: '{n} of {m} accounts',
scanLast: 'Last updated on',
scanProgress: 'Wallet {i} of {n}',
scanUpdated: 'updated',
scanFailedN: 'failed',
proposalOne: 'proposal',
proposalMany: 'proposals',
scanNever: 'Not updated yet',
scanAll: 'Update',
scanning: 'Scanning…',
scanningTx: 'Fetching transactions',
scanError: 'Update failed',
scanErrorWhy: 'Update failed: {reden}',
scanNotOnchain: 'Cannot be scanned on-chain',
lightningMovements: 'Lightning transactions updated',
addressesScanned: 'addresses scanned',
addressesFailed: 'failed',
dirIn: 'Received',
dirOut: 'Sent',
fee: 'fee',
unconfirmed: 'Unconfirmed',
addLabel: 'Add label',
txCount: 'transactions',
copyAddr: 'Copy address',
collapseToggle: 'Expand/collapse',
noTxs: 'No transactions for this source yet.',
matched: 'Also recorded as an event',
},
link: {
exact: 'Automatic match (address)',
soft: 'Suggested match (confirmed)',
manual: 'Linked manually',
},
match: {
add: 'Link to records',
linked: 'Linked',
toEvent: 'Link to event',
toTx: 'Link to on-chain transaction',
unlink: 'Unlink',
filter: 'Filter candidates…',
noCandidates: 'No candidates found',
unconfirmed: 'unconfirmed',
},
convert: {
title: 'Convert',
main: 'Main unit',
sub: 'Subunit',
apply: 'Apply',
pieces: 'Per piece',
product: 'Product',
count: 'Count',
},
portfolios: {
maxFree: 'The free version is limited to {max} portfolio. A license removes that limit; nothing is removed in the meantime.',
title: 'Portfolios',
switchFailed: 'Switching failed.',
nameRequired: 'A portfolio must have a name.',
nameTooLong: 'A portfolio name is at most {max} characters long.',
nameIsDirRef: '"{naam}" is not a name but a reference to a folder.',
nameForbiddenChars: 'A portfolio name cannot contain any of these characters: < > : " / \\ | ? *',
nameTrailing: 'A portfolio name cannot end with a space or a period.',
nameLeadingSpace: 'A portfolio name cannot start with a space.',
nameReserved: '"{naam}" is a reserved name in Windows and cannot become a folder.',
nameTaken: '"{naam}" is a name the app uses itself; choose another one.',
activeCannotRename: '"{naam}" is the portfolio that is open now and cannot be renamed. Switch to another portfolio first; the app restarts when you do.',
activeCannotArchive: '"{naam}" is the portfolio that is open now and cannot be deleted. Switch to another portfolio first; the app restarts when you do.',
unknownPortfolio: 'There is no portfolio "{naam}".',
nameInUse: 'There is already a portfolio "{naam}"; names that differ only in capitals or spelling count as the same.',
archiveFull: 'The archive is full of folders named "{naam}"; clean up a few first.',
notInArchive: 'There is no "{naam}" in the archive.',
passwordRequired: 'Enter a password.',
intro: 'Each portfolio is a separate set of records: its own database and its own secrets, in its own folder. Exactly one is always open.',
openNow: 'Open now',
activate: 'Open…',
activateConfirm: 'Switch to "{naam}"? The app restarts to do this.',
activateWaiting: 'The app is restarting…',
activateNoSupervisor: 'The choice is saved, but this app was started without the supervisor (npm run start:server). Close the app and start it again to work in "{naam}".',
create: 'New portfolio…',
createName: 'Name',
createNameHint: 'The name becomes the folder name on disk.',
createCurrency: 'Base currency',
createDone: 'Portfolio "{naam}" created.',
copy: 'Copy…',
copyTitle: 'Copy of "{naam}"',
copyName: 'Name of the copy',
copyConfirm: 'Copy',
copyDone: 'Portfolio "{naam}" created as a copy of "{bron}".',
createHint: 'New portfolio gives fresh records without connections. You copy a portfolio from the list; a copy takes the database and the secrets along together, because a secret belongs to a row and only fits that database.',
createCurrencyHint: 'The base currency is the currency the portfolio calculates in and shows all amounts in. You choose it for a new portfolio and after that it is fixed; a copy keeps the currency of the original.',
rename: 'Rename…',
renameTo: 'New name',
renameDone: 'Renamed to "{naam}".',
renameActive: 'The portfolio that is open now cannot be renamed: its database is open. Switch to another one first.',
remove: 'Delete…',
removeConfirm: 'Delete portfolio "{naam}"? The folder moves to the archive; nothing is erased. Type the name to confirm.',
removeTypeLabel: 'Type the name',
removeMismatch: 'That is not the name; nothing was changed.',
removeDone: '"{naam}" is now in the archive.',
empty: 'There is no other portfolio yet.',
noDatabase: 'no database yet',
lastUsed: 'last used',
never: 'not used yet',
archiveTitle: 'Archive',
archiveIntro: 'Deleted portfolios are kept here. They no longer count anywhere, but the files still exist.',
archiveEmpty: 'The archive is empty.',
purge: 'Delete permanently…',
purgeConfirm: 'Permanently delete the folder of "{naam}" and everything in it? The database, secrets and history will be gone. This cannot be undone. Type the name to confirm.',
purgeDone: '"{naam}" has been permanently deleted.',
settingsTitle: 'Settings of this portfolio',
hintTitle: 'What you see here',
authTitle: 'Access to this portfolio',
authNone: 'No password set. The app can therefore only be reached from this machine.',
authSet: 'A password is set.',
authEnv: 'Set through the environment variable ASSETAPP_PASSWORD. As long as that is set, it overrides what you enter here.',
authChange: 'Set or change…',
authClear: 'Clear…',
authPassword: 'Password',
authClearConfirm: 'Remove the password of this portfolio? After that the app can only be reached from this machine.',
authDone: 'Saved. It applies from the next time the app starts.',
authClearedDone: 'Removed. It applies from the next time the app starts.',
authLogout: 'Sign out',
authLogoutConfirm: 'Sign out? You need to enter the password again to continue.',
authHint: 'Access from another device requires a certificate and sign-in credentials. The certificate belongs to this installation; the credentials to this portfolio.',
startYearTitle: 'Start year of these records',
startYearLabel: 'Start reports at',
startYearAuto: 'Automatic (from the first entry)',
startYearAutoState: 'Automatic: reports start at the first reference date after the first entry, {jaar}.',
startYearState: 'Reports start at reference date January 1, {jaar}. The first entry is in {eerste}.',
startYearEmpty: 'Nothing has been recorded yet, so there is nothing to limit. This becomes visible as soon as there is an entry or a balance.',
startYearHint: 'Only needed if your records go far back: with a first entry in 1984 the taxes page creates 42 reference date columns and asks the price source for as many historical points. Nothing is lost: the positions still include everything before the start year, only fewer columns are shown.',
mwrTitle: 'Return method',
mwrLabel: 'Calculate the money-weighted return with',
mwr_dietz: 'Modified Dietz (default)',
mwr_irr: 'Internal rate of return (IRR)',
mwrState_dietz: 'The return is divided by the average invested capital: each deposit counts in proportion to how long it was there.',
mwrState_irr: 'The return is the annual rate that exactly explains your deposits and withdrawals. Where none exists, the figure falls back to Modified Dietz.',
mwrHint: 'This changes the percentages on the taxes page. Modified Dietz always gives a figure; IRR is more accurate but does not always have a solution, for example with a position that drops to zero in between. The chosen method is always shown with the figure.',
},
dbfile: {
title: 'All records',
passTooShort: 'Choose a password of at least 8 characters for the backup.',
notABackup: 'This file is not an AssetApp backup (too short).',
notABackupUseRestore: 'This file is not an AssetApp backup. You restore a separate .sqlite file with "Restore".',
unknownBackupVersion: 'Unknown backup version ({versie}); this app knows version {kent}.',
decryptFailed: 'Decryption failed: wrong password, or the file is damaged.',
noManifest: 'Backup damaged: no manifest found.',
manifestUnreadable: 'Backup damaged: the manifest is unreadable.',
manifestLengths: 'Backup damaged: the lengths in the manifest do not match the content.',
secretsUnreadable: 'Backup damaged: the secrets file is not readable JSON.',
notReadableSqlite: 'This is not a readable SQLite file ({reden}).',
noSchemaTable: 'This file has no Schema table. A database from before the baseline can no longer be converted: the conversion script only exists in the git history (git log --all -- scripts/baseline-convert.mjs).',
noReadableVersion: 'The Schema table contains no readable version.',
versionBeforeBaseline: 'This database is version {versie}, from before the new setup (version {baseline}). Converting is no longer possible; the conversion script only exists in the git history (git log --all -- scripts/baseline-convert.mjs).',
versionNewerThanApp: 'This database is version {versie} and therefore newer than the app ({app}). Update the app before you restore it.',
emptyFile: 'Empty file received.',
notSqlite: 'This is not an SQLite file (the file header does not match).',
backup: 'Back up…',
backupPass: 'Password for the backup',
backupPassAgain: 'Repeat password',
backupPassMismatch: 'The two passwords do not match.',
backupDone: 'Backup created. Keep the password safe: without the password the backup cannot be restored.',
export: 'Export database',
import: 'Restore…',
confirmRestoreBackup: 'Restore this backup? This replaces the database AND the secrets (secrets.json in the folder of this portfolio). The previous version of both is kept as .previous.',
restoredSecrets: 'Secrets restored as well:',
confirmImport: 'Replace the current database with this file? The previous one is kept as .previous next to the database file.',
importDone: 'Database restored',
importOrphans: 'Note, orphaned references found:',
hint: 'The backup contains the database and the secrets, encrypted. The export is only the database: enough to read, not enough to restore everything.',
fresh: 'Start empty…',
confirmFresh: 'Start with empty records? A fresh database is put into use; the current one is kept as .previous next to the database file. Make a backup first if you might ever need it again.',
freshWord: 'empty',
freshTypeLabel: 'Type the word to confirm',
freshWordMismatch: 'That is not the requested word; nothing was changed.',
freshDone: 'Empty records in use',
},
import: {
title: 'Import',
fileLabel: 'CSV file',
read: 'Read',
template: 'Blank template',
formatHint: 'Default format = the Bitvavo export (tab- or comma-separated). Your own files with the same headers also work; optional column "Account".',
noFile: 'Choose a file first.',
readError: 'Reading the file failed.',
origin: 'Origin',
originPh: 'e.g. Bitvavo',
summary: 'Summary',
nEvents: 'as event',
nSkipped: 'skipped',
account: 'Account (exchange) for this import',
chooseAccount: '(choose account)',
newAccount: '+ new exchange account…',
newAccountPh: 'Name of new account',
assetsTitle: 'Assets',
assetOk: 'linked',
assetMissing: 'no asset: create it under System → Assets (rows are skipped)',
addresses: 'Address destinations (withdrawals)',
destAccount: '(destination account)',
noSource: '(no specific tracking source)',
alreadyLinked: 'already linked',
process: 'Create events',
needAccount: 'Choose or create the exchange account first.',
needDest: 'Choose a destination account for each address.',
done: 'Import processed',
processFailed: 'Processing failed',
resCreated: 'created',
resUpdated: 'overwritten',
resKept: 'kept',
resUnchanged: 'unchanged',
resSkipped: 'skipped',
rows: 'rows',
conflictsTitle: 'Existing records',
conflictsIntro: 'These records already exist. By default they are overwritten; set one to "Keep" to leave the existing version in place.',
colField: 'Field',
colExisting: 'Existing',
colImported: 'Imported',
keep: 'Keep',
overwrite: 'Overwrite',
allKeep: 'Keep all',
allOverwrite: 'Overwrite all',
continue: 'Continue',
fType: 'Type',
fDate: 'Date',
fAmount: 'Amount',
fPrice: 'Price',
fFee: 'Fee ({munt})',
fFeeUnit: 'Fee',
notBookedTitle: 'These lines are not recorded',
feeNotBooked: 'Line {regel}: fees on interest, or fees in the asset itself on a purchase, are not counted anywhere. Record this line manually.',
fFrom: 'From',
fTo: 'To',
fAddress: 'Address',
resDeleted: 'deleted',
multiTitle: 'Multiple matches',
multiIntro: 'One import line matches several existing records. The import line is created; for each existing record, choose whether to leave it (Ignore) or delete it.',
importRow: 'Import line',
ignore: 'Ignore',
delete: 'Delete',
linkedNoDelete: 'linked, cannot be deleted',
identical: 'Identical',
},
health: {
summary: '{n} findings.',
start: 'Run check',
again: 'Check again',
lastRun: 'Last check: {wanneer}.',
neverRun: 'This check has never been run.',
checking: 'Check {i} of {n}: {naam}…',
checkFailed: 'This check could not be run:',
slowest: 'The slowest check was "{naam}" ({s} seconds).',
more: 'And {n} more. The full list is in the table itself.',
accept: 'This is correct',
acceptConfirm: 'This finding disappears from the report as long as the situation stays the same. If something changes (a case is added, or a count changes), it appears again.',
accepted: 'Accepted. This finding is now listed under the accepted findings at the bottom.',
severityWarn: 'Probably unintended',
severityInfo: 'For information',
acceptedTitle: 'Accepted findings',
acceptedNone: 'No findings accepted yet.',
unaccept: 'Show again',
acceptUnknownKind: 'That kind of finding does not exist.',
acceptNeedsSummary: 'An accepted finding needs a readable summary.',
allClear: 'No findings.',
allClearWhy: 'This report looks at duplicate entries, balances that are not reconciled, gaps and delays in the price history, suspicious prices, transfers without a counterpart and a few technical references.',
kind: {
duplicate_events: 'Duplicate entries',
assets_without_balance: 'Assets without a balance',
unreconciled_valuations: 'Balances that are not reconciled',
stale_prices: 'Outdated prices',
late_price_history: 'Price history starts too late',
price_gaps: 'Gaps in the price history',
price_stopped: 'Holding without a current price',
transfer_without_counterpart: 'Transfer without a counterpart',
unlinked_transactions: 'Unlinked transactions',
coverage_without_asset: 'Coverage without an asset',
price_unit_swap: 'Price in the wrong unit',
price_outlier: 'Outlier in the price history',
price_sources_disagree: 'Sources disagree',
price_not_positive: 'Price of zero or less',
price_in_future: 'Price in the future',
fee_without_effect: 'Fees that count nowhere',
booking_price_deviates: 'Entry price far from the daily price',
price_origin_derivable: 'Price origin can be derived',
},
why: {
duplicate_events: 'The same entry appears twice: same asset, type, moment and quantity. Almost always one purchase that was entered twice. For a product entry the product also counts, because different coins of the same weight are not the same.',
assets_without_balance: 'You hold this asset, but there is not a single balance against it. That is fine: records that run on the ledger are complete without balances. It only means there is nothing to check that ledger against.',
unreconciled_valuations: 'A balance differs from what the entries say, and that difference has not yet been recorded or accepted. You can resolve it on To do.',
stale_prices: 'The latest price of this asset is old. The current value then falls back to that point, however old it is, and that is not shown anywhere.',
late_price_history: 'You have held this asset longer than the price history goes back. Everything before the first price point therefore cannot be valued; you can add a price point manually on Price history.',
price_gaps: 'There is a gap between two price points, counted in days without a price since your first entry, as on Price history. The daily grid carries the previous price forward up to the age limit and gives nothing after that.',
price_stopped: 'You hold this asset now, but the latest price is older than the app carries it forward. On a reference date after that price it therefore cannot be valued. Find a source, or add a price manually on Price history.',
transfer_without_counterpart: 'A transfer names only one account. That can be correct (to or from outside), but between your own accounts there should be a counterpart.',
unlinked_transactions: 'A transaction on the chain is not linked to any entry. It then counts in your balance but not in your ledger.',
coverage_without_asset: 'A source claims to provide a symbol that is not an asset here. Not wrong, but good to know before you rely on it.',
price_unit_swap: 'This price is a factor 31 off the price before it, and that is the number of grams in a troy ounce. Almost always a price per ounce stored as a price per gram, or the other way around. Correct or delete it on Price history, under Prices.',
price_outlier: 'This price is a factor three or more above or below both its neighbors. No market does that in a day; a zero too many or too few does.',
price_sources_disagree: 'Two sources give prices for the same day that are far apart. That is not an error of either one, but a choice: the app uses the most recently written row.',
price_not_positive: 'A price of zero or less is not a price. The app does not count this row, so it is there but does nothing.',
price_in_future: 'This price has a moment that has not happened yet. That can only be a typo in the date.',
fee_without_effect: 'This entry carries fees in a place no calculation reads: fees in money on interest, or fees in the asset itself on a purchase or interest. They are on it but do nothing.',
booking_price_deviates: 'The price of this purchase or sale is more than 20% off the price of that day, or a factor 31 off (gram versus troy ounce). A spread of a few percent is normal; this is usually a typo, a wrong date or the wrong unit.',
price_origin_derivable: 'For these entries it is not recorded where the price came from, but it is exactly the daily price: the form filled it in itself. The button gives them the origin Daily price. Anything that differs stays unknown, because then it cannot be told whether it was paid or the price at the time.',
},
fillOrigins: 'Fill in origin',
fillOriginsConfirm: 'These entries get the origin Daily price. The change is written to the change log.',
fillOriginsDone: 'The origin was filled in for {n} entries.',
},
data: {
title: 'Data',
table: 'Table',
rows: 'rows',
empty: 'No rows.',
delete: 'Delete',
confirmDelete: 'Permanently delete this row?',
clear: 'Clear table',
confirmClear: 'Permanently delete all records from this table? This cannot be undone.',
},
signals: {
title: 'Bitcoin Signals & Charts',
noHistory: 'No price history in storage.',
noAssetForHistory: 'No {symbool} asset found for price history.',
live: 'LIVE DATA',
price: 'Price',
tabPrice: 'Bitcoin price',
tabPl: 'Power Law',
tabWma: 'Weekly averages',
tabMayer: 'Mayer Multiple',
sigPlLabel: 'Power Law',
sigWmaLabel: '200-week MA',
sigMayerLabel: 'Mayer Multiple',
priceTitle: 'Bitcoin price',
priceSub: 'Historical price',
plTitle: 'Power Law Corridor',
plSub: 'Live price vs. long-term trend · log-log',
wmaTitle: '50- and 200-week average',
wmaSub: '200-week: historical bottom zone · 50-week: dividing line between the regimes',
mayerTitle: 'Mayer Multiple',
mayerSub: 'Price ÷ 200-day average · over-/undervaluation',
log: 'Logarithmic',
lin: 'Linear',
zoomRecent: 'Zoom recent',
resetZoom: 'Reset zoom',
fullscreen: 'Full screen',
loading: 'Loading…',
error: 'Cannot load data',
mayerInfo1Title: 'Mayer < 1.0:',
mayerInfo1: 'price is below the 200-day average. Historically a strong but rare zone (local bottoms).',
mayerInfo2Title: 'Mayer 1.0 to 2.4:',
mayerInfo2: 'normal zone. Price above the 200-day average, but not yet stretched.',
mayerInfo3Title: 'Mayer ≥ 2.4:',
mayerInfo3: "historically overheated (Mayer's own threshold). Often near cycle tops.",
hintTitle: 'What you see here',
hintLightsTitle: 'The three signals',
hintLights: 'The lights summarize the three charts and stay in place while you move through them. Click one to go to that chart. Green, yellow and red are a judgment here, and the only place on this page where color means that.',
hintColorsTitle: 'The colors in the charts',
hintColors: 'Each line is a shade of the accent color: solid is the price, one shade lighter is the signal line next to it, and the lightest is the reference or the band behind it. So not a color code, but a ranking.',
hintPl: 'The Power Law is a straight line in log-log: the price grows as a power of the time since the genesis block. The line is the fit, not a prediction.',
hintPlBands: 'The bands are a fixed factor on that fit, set by the app to what has roughly held historically. They are a drawing and never the data.',
hintPlProjection: 'The lines continue one year beyond the latest price. Short on purpose: drawing further ahead suggests a predictive value this fit does not have.',
hintWma200: 'The 200-week average is the slow bottom zone of the cycle.',
hintWma50: 'The 50-week average is the dividing line between the two regimes: support in a rising market, and losing it has historically coincided with the start of the decline.',
leg: {
btc: 'Bitcoin', fit: 'Power Law fit', lower: 'Lower band', upper: 'Upper band',
wma: '200-week MA', wma50: '50-week MA', mayer: 'Mayer Multiple',
},
sig: {
plStrong: 'STRONG BUY ZONE', plBuy: 'BUY ZONE', plAbove: 'ABOVE TREND', plFar: 'FAR ABOVE TREND',
wmaBuy: 'BUY ZONE', wmaAbove: 'ABOVE 200WMA × 1.2', wmaFar: 'FAR ABOVE 200WMA',
mayerLow: 'BUY ZONE', mayerMid: 'NEUTRAL', mayerHigh: 'OVERHEATED',
},
},
stub: {
title: 'Not built yet',
body: 'This page comes in a later phase. The skeleton and the database already work.',
},
enums: {
asset_kind: { crypto: 'Crypto', metal: 'Metals', fiat: 'Currencies' },
tax_category: { bank: 'Bank balance', overig: 'Other asset' },
tax_scope: { all: 'Counts', category: 'Listed separately only', none: 'Does not count' },
wealth_scope: { managed: 'Third-party wealth', none: 'Does not count' },
metal_form: { coin: 'Coin', bar: 'Bar', other: 'Other' },
displayUnit: { unit: 'Main unit', subunit: 'Subunit' },
location_kind: { exchange: 'Exchange', wallet: 'Wallet', lightning: 'Lightning', card: 'Card', bank: 'Bank', vault: 'Vault' },
account_kind: { exchange: 'Exchange', wallet: 'Wallet', lightning: 'Lightning', card: 'Card', bank: 'Bank', vault: 'Vault' },
event_source: { manual: 'Manual', import: 'Import', reconcile: 'Reconcile', lightning: 'Lightning' },
event_type: { buy: 'Buy', sell: 'Sell', transfer: 'Transfer', interest: 'Interest', reservation: 'Reservation' },
event_price_origin: { paid: 'Paid', market_day: 'Daily price', market_moment: 'Price at the time', none: 'Gift' },
valuation_source: { onchain: 'On-chain', manual: 'Manual', statement: 'Statement' },
interest_cadence: { term_end: 'End of term', annual: 'Annually', quarterly: 'Quarterly', monthly: 'Monthly', weekly: 'Weekly' },
interest_rate_kind: { fixed: 'Calculated', variable: 'Manual or import' },
reconcile_status: { pending: 'Open', accepted_trade: 'Buy/Sell', accepted_transfer: 'Transfer', accepted_interest: 'Interest', ignored: 'Ignored', auto_linked: 'Auto-linked' },
},
};