Wealthfolio logo Wealthfolio
Download
Docs
Addon Localization

Addon Localization

Format values and translate addon interfaces using the user's Wealthfolio locale.


Last updated

Addon Localization

Wealthfolio addons run inside a sandboxed iframe that follows the host application’s language and regional formatting settings. Formatting controls numbers, currencies, and dates; translation controls the strings owned by your addon. Both update when the user changes their settings.

The sandbox localization runtime ships with Wealthfolio 3.8. Addons using these APIs must set both sdkVersion and minWealthfolioVersion to 3.8.0 or newer.

Format numbers, currencies, and dates

The UI language and formatting region are separate settings. A user may read Wealthfolio in French while formatting amounts as en-US. Do not hardcode locales or date patterns. Use the formatting hooks provided by @wealthfolio/ui:

import {
  useAmountFormatting,
  useDateFormatting,
  useLocalizationSettings,
  useNumberFormatting,
} from '@wealthfolio/ui';

function HoldingRow({ value, currency, asOf }: Props) {
  const { formatAmount } = useAmountFormatting();
  const { formatDate } = useDateFormatting();
  const { formatPercent } = useNumberFormatting();

  return (
    <div>
      {formatAmount(value, currency)}{formatDate(asOf)}{formatPercent(0.042)}
    </div>
  );
}

Available hooks include:

  • useAmountFormatting()formatAmount, formatPrice, formatCompactAmount, formatRoundedAmount, formatCurrencySymbol, and currencyFractionDigits.
  • useNumberFormatting()formatPercent, formatQuantity, formatDecimal, locale-aware parseNumber, and decimal/group separators.
  • useDateFormatting()formatDate, formatDateTime, formatTime, date-range helpers, and locale-aware parseDate.
  • useLocalizationSettings() — the raw { locale, uiLocale, timezone } settings.

Translate addon-owned strings

Register translations once in enable() before the first render, then use the translation hook in React components:

import {
  registerTranslations,
  useAddonTranslation,
  type AddonContext,
} from '@wealthfolio/addon-sdk';

export default function enable(ctx: AddonContext) {
  registerTranslations({
    en: {
      title: 'Dividend Forecast',
      greeting: 'Hello {{name}}',
      holdings_one: '{{count}} holding',
      holdings_other: '{{count}} holdings',
    },
    fr: {
      title: 'Prévision de dividendes',
      greeting: 'Bonjour {{name}}',
    },
  });

  // Register routes and sidebar items.
}

function Title() {
  const { t, language } = useAddonTranslation();
  return <h1 lang={language}>{t('title')}</h1>;
}

Behavior and fallback rules

  • Translation resources are private to the current addon. They cannot read or overwrite the host’s strings, and other addons cannot see them.
  • The language always follows Wealthfolio. Addons cannot change it.
  • Missing strings fall back to the addon’s en bundle and then to the translation key. Always ship a complete English bundle.
  • Interpolation uses {{name}}; plurals use _one and _other suffixes with t('holdings', { count }).
  • Components re-render on language changes and late registerTranslations() calls.
  • Namespace and language overrides passed to t() are ignored, and $t() nesting inside resource values is disabled.

Supported language keys

The host currently resolves en, fr, de, es, pt, zh, zh-Hant, ja, ko, and it. Regional aliases normalize to their supported language: for example, fr-CA becomes fr and Traditional Chinese aliases such as zh-TW, zh-HK, and zh-MO become zh-Hant.

Register zh-Hant separately from zh. A missing Traditional Chinese string falls back to English, not Simplified Chinese.

Valid language bundles outside the host’s supported set may be registered, but they are never selected. Invalid language keys are ignored with a warning.

Using another localization library

The host does not provide react-i18next or i18next as external dependencies. If your addon needs ICU messages, its own language switcher, or another language, bundle your own localization library. The addon sandbox blocks direct network access, so bundle translation resources instead of loading them from a remote backend.