Back to Readest

I18n

apps/readest-app/docs/i18n.md

0.10.61.6 KB
Original Source

i18n Guide

Readest uses a key-as-content approach — English strings are the translation keys. The English locale (en/translation.json) is empty because keys serve as content. Other locales contain actual translations.

In React Components

tsx
import { useTranslation } from '@/hooks/useTranslation';

const _ = useTranslation();
_('Progress synced');

In Non-React Modules

Two-step process:

1. Declaration — Use stubTranslation to mark strings for scanner extraction (returns key as-is, does NOT translate):

ts
import { stubTranslation as _ } from '@/utils/misc';

// These calls only register keys for extraction
_('Reveal in Finder');
_('Reveal in Explorer');

2. Usage — In the React component that consumes the value, apply the real _() from useTranslation:

tsx
const _ = useTranslation();
const label = _(getRevealLabel()); // translates at runtime

Extraction & Translation

bash
pnpm i18n:extract    # Scans codebase, adds new keys with __STRING_NOT_TRANSLATED__
  • Translation files: public/locales/<locale>/translation.json
  • Only _('KEY') and _('KEY', options) patterns are recognized by i18next-scanner

Rules

  • stubTranslation is for extraction only — always apply _() from useTranslation in the component for runtime translation.
  • Fallback: when no translation exists, the English key itself is displayed.
  • Error messages: register keys with stubTranslation in utility modules (e.g. src/services/errors.ts), return the English key from helpers, wrap with _() in the component.