Translations
YapYap's own windows, menus, dialogs and notifications are translatable. WhatsApp itself is not part of this: it chooses its own language. The design is in ADR 0012.
YapYap ships in English only for now. A language ships once a native speaker has reviewed it, and machine-translated catalogs are not accepted. Translations arrive as pull requests.
Catalogs
Each language is one JSON file in apps/desktop/src/shared/messages/locales/, named after its language tag: pt.json, pt-BR.json, ar.json. The format is i18next JSON v4, which translation tools such as Weblate read and write:
- Keys nest exactly as in
en.json, the English source. Never rename or translate a key. No key contains a., which translation tools read as nesting. - Values are plain text. Markup such as
<b>or&is rejected, and YapYap always shows text as text. is a placeholder that YapYap fills in, such as an account or a extension name. Keep every placeholder English has, spelled the same, wherever your language puts it.- A message that counts has one key per plural form:
unread_one,unread_other, and_zero,_two,_fewor_manywhere your language uses them (CLDR plural rules).is the number, and a form such as_onemay leave it out.
A catalog does not have to be complete. Any key it lacks, or whose placeholders differ from English's, shows in English, so a partial translation is still usable.
Notes for translators
menu:&marks the access key on Windows and Linux, and macOS ignores it. Keep one&per label, before a letter of your translation that no other item in the same menu uses.extensions.notificationTitleandmenu.extensionCommand: these name the extension first, so its notifications and commands never pass for WhatsApp's or YapYap's own. Keepat the start.notifications.titled: with several accounts, the account a notification comes from heads it.report.issueTitleandreport.crashTitlebecome GitHub issue titles, which the user can still change.report.crashTitleWithkeeps the crash's, so reports of one crash can be found together.settings.fieldsare grouped by settings section, then keyed by setting, and theiroptionsby the values the settings file stores. Translate only the text.extensions.capabilitiesdescribes what each permission lets an extension do, in the words the consent window shows before installing.
Checks
pnpm lint runs node scripts/src/bin/check-catalogs.ts, which CI runs on every pull request. It fails when a catalog:
- is not valid JSON;
- is not named after a language tag;
- has a key with a
.in it (English included); - has keys English lacks;
- has placeholders that differ from English's;
- lacks a plural form its language needs;
- contains markup.
It also fails when the generated Messages type no longer matches en.json.
Changing English text
UI text lives only in en.json. Lint rejects literal text in the UI code. After adding or changing English text, run:
node scripts/src/bin/i18n-types.tsIt regenerates messages.generated.ts, the type that every catalog and every call site follows. Messages with placeholders or plural forms are functions of named values:
en.dialogs.removeAccount.message({ name: account.name });
en.tray.unread({ count: 3 });