Fabric supports multiple languages through its internationalization system. The system automatically detects your preferred language from environment variables and provides localized messages.
Fabric follows POSIX standards for locale detection with the following priority order:
- Explicit language flag:
--languageor-g(highest priority) - LC_ALL: Complete locale override environment variable
- LC_MESSAGES: Messages-specific locale environment variable
- LANG: General locale environment variable
- Default fallback: English (
en) if none are set or valid
# Use explicit language flag
fabric --language es --pattern summarize
# Use LC_ALL environment variable
LC_ALL=fr_FR.UTF-8 fabric --pattern summarize
# Use LANG environment variable
LANG=de_DE.UTF-8 fabric --pattern summarize
# Multiple environment variables (LC_ALL takes priority)
LC_ALL=es_ES.UTF-8 LANG=fr_FR.UTF-8 fabric --pattern summarize
# Uses Spanish (es_ES) because LC_ALL has higher priorityThe system automatically normalizes various locale formats:
en_US.UTF-8→en-USfr_FR@euro→fr-FRzh_CN.GB2312→zh-CNde_DE.UTF-8@traditional→de-DE
Special cases:
CorPOSIX→ treated as invalid, falls back to English
Translations are loaded from multiple sources in this order:
-
Embedded files (highest priority): Compiled into the binary
- Location:
internal/i18n/locales/*.json - Always available, no download required
- Location:
-
User config directory: Downloaded on demand
- Location:
~/.config/fabric/locales/ - Downloaded from GitHub when needed
- Location:
-
GitHub repository: Source for downloads
- URL:
https://raw.githubusercontent.com/danielmiessler/Fabric/main/internal/i18n/locales/
- URL:
- English (
en): Default language, always available - Spanish (
es): Available in embedded files
To add support for a new language:
-
Create a new JSON file:
internal/i18n/locales/{lang}.json -
Add translations in the format:
{ "message_id": "localized message text" } -
Rebuild Fabric to embed the new translations
Translation files use JSON format with message IDs as keys:
{
"html_readability_error": "use original input, because can't apply html readability"
}Spanish example:
{
"html_readability_error": "usa la entrada original, porque no se puede aplicar la legibilidad de html"
}The i18n system is designed to be robust:
- Download failures: Non-fatal, falls back to embedded translations
- Invalid locales: Skipped, next priority locale used
- Missing translations: Falls back to English
- Missing files: Uses embedded defaults
Error messages are logged to stderr but don't prevent operation.
# Set system-wide locale
export LANG=en_US.UTF-8
# Override all locale categories
export LC_ALL=fr_FR.UTF-8
# Set only message locale (for this session)
LC_MESSAGES=es_ES.UTF-8 fabric --pattern summarize
# Check current locale settings
localeYou can test locale detection without changing your system settings:
# Test with French
LC_ALL=fr_FR.UTF-8 fabric --version
# Test with Spanish (if available)
LC_ALL=es_ES.UTF-8 fabric --version
# Test with German (will download if available)
LC_ALL=de_DE.UTF-8 fabric --versionThis is normal when requesting a language not yet available. The system will fall back to English.
Check your environment variables:
echo $LC_ALL
echo $LC_MESSAGES
echo $LANGEnsure they're in a valid format like en_US.UTF-8 or fr_FR.
Remember the priority order:
--languageflag overrides everythingLC_ALLoverridesLC_MESSAGESandLANGLC_MESSAGESoverridesLANG
The locale detection system:
- Uses
golang.org/x/text/languagefor parsing and validation - Follows BCP 47 language tag standards
- Implements POSIX locale environment variable precedence
- Provides comprehensive test coverage
- Handles edge cases gracefully
For developers working on the codebase, see the implementation in:
internal/i18n/locale.go: Locale detection logicinternal/i18n/i18n.go: Main i18n initializationinternal/i18n/locale_test.go: Test suite