Skip to main content

Internationalization

Are you interested in bringing Actual to a broader audience by translating and localizing the app into new languages? Great! This guide will show you how to get started. Adding translations can be a great first step into contributing to open-source software.

Community translations

Currently, Actual Budget is not yet ready to receive community translations.

Current status

Actual is currently being prepared for internationalization (i18n). This means that initially everything in the app was English, but we're slowly marking all texts for translation.

Marking for translation

Developing translated software requires that every text shown to the user passes through a translation function. Actual uses i18next to achieve this goal.

Strings in Actual are translated by their natural English language version. The project does not use artificial keys to select the appropriate translated text from the message catalog.

Using natural language keys

Consider the text "Welcome to Actual Budget". When marking strings for translation using natural language, this string also becomes the key used to translate it into other languages. This is in contrast to a commonly used alternative of using artificial keys, which would look like "text_welcome". Actual Budget does not use these keys.

When preparing your translatable strings, please use complete units to translate. If there is a cohesive paragraph with multiple sentences, mark the entire paragraph as one translatable string. Do not split it into multiple texts.

The translation framework provides two primary methods for translation:

t() function

The t() function is the simplest form of translation, it accepts the text to be translated and an optional object with interpolation variables. We're using the i18next singleton instance. You can use the hook within React components to get a reference to it.

import { useTranslation } from 'react-i18next';

function MyComponent() {
const { t } = useTranslation();

return <p>{t('Hello World')}</p>;
}

At runtime, it will select the translation from the currently active locale. You can also add variables to interpolate:

const withPlaceholder = t('Welcome home, {{name}}!', { name: 'Anita' });

For pluralalization, please use the plural form for the default text. The placeholder variable must be named count:

const manyItems = t('You selected {{count}} items', { count: 4 });

i18next will take care of proper pluralization rules in the currently active language and provide multiple different forms if required.

<Trans> component

When translating text with simple HTML tags or other React components, you will need to use the <Trans> component.

import { Trans } from 'react-i18next';

function MyComponent() {
return (
<Trans>
Click <Link href={url}>here</Link> to become a millionaire.
</Trans>
);
}

Interpolation with <Trans>

Handling placeholder variables and pluralization within the <Trans> React component is handled slightly differently. For more details, please refer to i18next-react's documentation.

import { Trans } from 'react-i18next';

function MyComponent() {
const person = { name: "Pedro" };
// You can use an object literal within <Trans>!
return (
<Trans>
Your name is {{ name: person.name }}.
</Trans>
);
// This will result in the translation string:
// "Your name is {{name}}."
}