Files
sure/app/models/concerns/accountable.rb
Brendon Scheiber 7411db5689 feat(i18n): add Hungarian translations for strings extracted in #1806 (#1817)
* add missing Hungarian translations for newly extracted strings

Replace hard-coded UI strings with I18n lookups across controllers, models and views (breadcrumbs, dashboard, reports, settings, transactions, balance sheet, MFA status). Update models to use translations for category defaults, account/display names, classification group and period labels; remove a few hardcoded display_name methods. Add and update numerous locale files (English and extensive Hungarian translations, plus model/view/doorkeeper entries) to provide the required keys. These changes centralize copy for localization and prepare the app for Hungarian/English UI text.

* Pluralize account type labels; tidy Crypto model

Update English locale account type labels to use plural forms for consistency (Investment(s), Properties, Vehicles, Other Assets, Credit Cards, Loans, Other Liabilities). Also remove an extra blank line in app/models/crypto.rb to tidy up formatting.

* Back to singular

* fix(i18n): separate singular and group account labels

* Update _accountable_group.html.erb

* Use I18n plural names for account types

Change Accountable#display_name to look up pluralized account type names via I18n (accounts.types_plural.<underscored_class>) with a fallback to the legacy display logic. Add legacy_display_name helper to preserve previous behavior (singular for Depository and Crypto, pluralized otherwise). Add corresponding types_plural entries in English and Hungarian locale files for various account types.

---------

Co-authored-by: Juan José Mata <jjmata@jjmata.com>
Co-authored-by: sure-admin <sure-admin@splashblot.com>
2026-05-18 20:49:28 +02:00

132 lines
3.2 KiB
Ruby

module Accountable
extend ActiveSupport::Concern
TYPES = %w[Depository Investment Crypto Property Vehicle OtherAsset CreditCard Loan OtherLiability]
# Define empty hash to ensure all accountables have this defined
SUBTYPES = {}.freeze
def self.from_type(type)
return nil unless TYPES.include?(type)
type.constantize
end
included do
include Enrichable
has_one :account, as: :accountable, touch: true
end
class_methods do
def classification
raise NotImplementedError, "Accountable must implement #classification"
end
def icon
raise NotImplementedError, "Accountable must implement #icon"
end
def color
raise NotImplementedError, "Accountable must implement #color"
end
# Given a subtype, look up the label for this accountable type
# Uses i18n with fallback to hardcoded SUBTYPES values
def subtype_label_for(subtype, format: :short)
return nil if subtype.nil?
label_type = format == :long ? :long : :short
fallback = self::SUBTYPES.dig(subtype, label_type)
I18n.t(
"#{name.underscore.pluralize}.subtypes.#{subtype}.#{label_type}",
default: fallback
)
end
# Convenience method for getting the short label
def short_subtype_label_for(subtype)
subtype_label_for(subtype, format: :short)
end
# Convenience method for getting the long label
def long_subtype_label_for(subtype)
subtype_label_for(subtype, format: :long)
end
def favorable_direction
classification == "asset" ? "up" : "down"
end
def singular_display_name
I18n.t("accounts.types.#{name.underscore}", default: legacy_singular_display_name)
end
def display_name
I18n.t("accounts.types_plural.#{name.underscore}", default: -> { legacy_display_name })
end
def legacy_display_name
return singular_display_name if name.in?([ "Depository", "Crypto" ])
singular_display_name.pluralize
end
def legacy_singular_display_name
case name
when "Depository"
"Cash"
when "Crypto"
"Crypto"
else
name.underscore.humanize
end
end
# Sums the balances of all active accounts of this type, converting foreign currencies to the family's currency.
# @return [BigDecimal] total balance in the family's currency
def balance_money(family)
accounts = family.accounts.active.where(accountable_type: self.name).to_a
foreign_currencies = accounts.filter_map { |a| a.currency if a.currency != family.currency }
rates = ExchangeRate.rates_for(foreign_currencies, to: family.currency, date: Date.current)
accounts.sum(BigDecimal(0)) { |account|
if account.currency == family.currency
account.balance
else
account.balance * (rates[account.currency] || 1)
end
}
end
end
def singular_display_name
self.class.singular_display_name
end
def display_name
self.class.display_name
end
def balance_display_name
"account value"
end
def opening_balance_display_name
"opening balance"
end
def icon
self.class.icon
end
def color
self.class.color
end
def classification
self.class.classification
end
end