| name | i18n-messaging |
| description | Manage and maintain i18n messaging or copy for Daedalus multi-language support. |
| user-invocable | true |
i18n Messaging
Manage and maintain i18n messaging for Daedalus multi-language support
Handles message extraction, validation, localization workflows, and schema compliance for Daedalus's internationalization system. Supports English (en-US) and Japanese (ja-JP) locales using react-intl and Format.js.
Message Schema
Messages in Daedalus follow a structured format using defineMessages() from react-intl:
{
messageKey: {
id: "namespace.context.messageKey",
defaultMessage: "!!!Message text with placeholders",
description: "Context/description for translators",
values?: Record<string, any>
}
}
ID Naming Convention
- Format:
namespace.context.messageKey (dot-separated)
- Prefix: All messages start with
!!! in defaultMessage
- Examples:
global.errors.fieldIsRequired
api.errors.IncorrectPasswordError
global.ada.name
Variable Placeholders
Messages with dynamic content use curly braces:
knownMnemonicWordCount: {
id: 'global.info.knownMnemonicWordCount',
defaultMessage: '!!!{actual} of {required} words entered',
values: { actual: 5, required: 12 }
}
Operations
1. Extract Messages
Extract all i18n messages from source code to generate message catalog.
yarn i18n:extract
What it does:
- Scans
source/**/*.{ts,tsx} files
- Extracts
defineMessages() and <FormattedMessage /> calls
- Ignores
.d.ts TypeScript declaration files
- Outputs to
translations/messages.json
- Records source file locations
When to use:
- After adding new messages with
defineMessages()
- Before running
i18n:check
- As part of
i18n:manage workflow
Output format:
[
{
"path": "source/main/ipc/handlers.ts",
"descriptors": [
{
"id": "global.errors.fieldIsRequired",
"defaultMessage": "!!!This field is required.",
"description": "Error message when required fields are left empty."
}
]
}
]
2. Check Translations
Validate translation files for consistency and completeness against extracted messages.
yarn i18n:check
What it does:
- Compares extracted messages with translation files
- Validates en-US and ja-JP locales
- Ensures all message IDs are present
- Detects missing or obsolete translations
- Uses
react-intl-translations-manager to manage lifecycle
When to use:
- After extracting new messages
- Before committing translation changes
- To validate message format across locales
Validates:
- All en-US messages have corresponding ja-JP translations
- No orphaned message IDs
- Message structure consistency (id, defaultMessage, description)
3. Manage Translations
Combined operation: extract messages AND validate translations in one command.
yarn i18n:manage
Equivalent to: yarn i18n:extract && yarn i18n:check
When to use:
- Primary workflow for updating i18n content
- Part of
check:all verification
- Before creating commits with messaging changes
Supported Locales
| Locale | Language | Directory |
|---|
| en-US | English | source/renderer/app/i18n/locales/en-US.json |
| ja-JP | Japanese | source/renderer/app/i18n/locales/ja-JP.json |
Locale Files Structure
source/renderer/app/i18n/locales/
├── defaultMessages.json # All extracted messages (auto-generated)
├── en-US.json # English translations (English only)
├── ja-JP.json # Japanese translations
├── whitelist_en-US.json # Approved en-US messages
├── whitelist_ja-JP.json # Approved ja-JP messages
└── terms-of-use/ # Locale-specific documents
Best Practices
Adding New Messages
- Use
defineMessages() or <FormattedMessage /> in source code
- Follow naming convention:
namespace.context.messageKey
- Include descriptive
description for translators
- Always prefix defaultMessage with
!!!
- Run
yarn i18n:extract to register new messages
Validating Message IDs
Do:
- Use hierarchical namespaces:
wallet.send.confirmButton
- Keep IDs consistent across related messages
- Document placeholder variables in description
- Use lowercase with dots as separators
Don't:
- Use spaces or special characters in IDs
- Duplicate IDs across features
- Leave placeholders undocumented
- Change ID format mid-project
Working with Placeholders
Messages with runtime values use curly braces:
notEnoughFunds: {
id: 'wallet.errors.notEnoughFunds',
defaultMessage: '!!!Remaining balance: {balance} ADA',
description: 'Error when insufficient funds'
}
<FormattedMessage
id="wallet.errors.notEnoughFunds"
defaultMessage="Remaining balance: {balance} ADA"
values={{ balance: walletBalance }}
/>
Translation Flow
- Extract: Run
yarn i18n:extract after code changes
- Check: Run
yarn i18n:check to validate
- Review: Update localized JSON files as needed
- Verify: Run
check:all before committing
- Commit: Include updated
translations/messages.json and locale files
Generated !!! Placeholders
yarn i18n:manage seeds missing locale entries from defaultMessage, so new keys in en-US.json and ja-JP.json can be written with the !!! prefix.
- Treat
!!! in locale files as a new or untranslated message marker, not polished release copy.
- This workflow does not remove the prefix automatically. If locale polish is in scope, manually replace new
en-US.json entries with approved English copy and add real Japanese translations in ja-JP.json before commit.
- If the task only covers extraction or catalog sync, keeping generated
!!! placeholders is acceptable, but document the follow-up translation work explicitly.
Related Files
| File | Purpose |
|---|
translations/translation-runner.ts | Validates translations (manages mapping) |
translations/formatter.js | Custom extraction format for Format.js |
translations/messages.json | Extracted message catalog |
source/renderer/app/i18n/global-messages.ts | Global message definitions |
source/renderer/app/i18n/errors.ts | Error message definitions |
source/renderer/app/i18n/types.ts | TypeScript types for messages |
Troubleshooting
Messages not extracted
- Verify
defineMessages() is imported from react-intl
- Check files are in
source/**/*.{ts,tsx} (not .d.ts)
- Run
yarn clear:translations then yarn i18n:extract
Translation validation fails
- Ensure all en-US messages have ja-JP equivalents
- Check message IDs match exactly (case-sensitive)
- Verify JSON format is valid in locale files
Missing or duplicate IDs
- Check for conflicting message keys across files
- Remove obsolete messages from translation files manually
- Re-run
yarn i18n:manage to refresh state
Template: Adding New Message
import { defineMessages } from 'react-intl';
export const componentMessages = defineMessages({
newMessageKey: {
id: 'feature.component.newMessageKey',
defaultMessage: '!!!Default English text',
description: 'Context for translators explaining where/how this message is used',
},
messageWithPlaceholder: {
id: 'feature.component.messageWithPlaceholder',
defaultMessage: '!!!You have {count} items',
description: 'Message showing item count with placeholder',
},
});
Then run: yarn i18n:manage