A modern, easy-to-use, feature-rich async-ready API wrapper for Discord written in Python
—
Disnake's internationalization system enables application commands to support multiple languages through Discord's native localization features. The system provides both high-level convenience classes and low-level protocols for custom localization implementations.
Container class for managing localized strings across different languages/locales.
class Localized(Generic[StringT]):
def __init__(
self,
string: StringT,
*,
key: Optional[str] = None,
**localizations: StringT
):
"""
Create a localized string container.
Parameters:
- string: Base/default string value
- key: Localization key for lookups
- localizations: Locale-specific string values
"""
def set(self, locale: Union[Locale, str], value: StringT) -> Self:
"""
Set localized value for a specific locale.
Parameters:
- locale: Target locale
- value: Localized string value
Returns:
Self for method chaining
"""
@property
def localizations(self) -> Dict[Locale, StringT]:
"""Dictionary of all localized values."""
@property
def key(self) -> Optional[str]:
"""Localization key for external lookup."""Represents a localized value with support for fallback languages and placeholder substitution.
class LocalizationValue:
def __init__(
self,
message: str,
key: Optional[str] = None,
**kwargs: Any
):
"""
Create a localization value with optional formatting.
Parameters:
- message: Base message string
- key: Localization key identifier
- kwargs: Format arguments for string interpolation
"""
def format(self, **kwargs: Any) -> LocalizationValue:
"""
Create new LocalizationValue with additional format arguments.
Parameters:
- kwargs: Format arguments to merge
Returns:
New LocalizationValue with combined formatting
"""Abstract protocol defining the interface for localization providers.
class LocalizationProtocol(ABC):
@abstractmethod
async def get(
self,
key: str,
locale: Locale,
*,
default: Optional[str] = None,
**kwargs: Any
) -> Optional[str]:
"""
Get localized string for key and locale.
Parameters:
- key: Localization key
- locale: Target locale
- default: Default value if key not found
- kwargs: Format arguments for string interpolation
Returns:
Localized string or None if not found
"""
@abstractmethod
async def bulk_get(
self,
keys: Sequence[str],
locale: Locale,
**kwargs: Any
) -> Dict[str, Optional[str]]:
"""
Get multiple localized strings at once.
Parameters:
- keys: List of localization keys
- locale: Target locale
- kwargs: Format arguments for all strings
Returns:
Dictionary mapping keys to localized strings
"""Default file-based localization provider that loads translations from JSON files.
class LocalizationStore(LocalizationProtocol):
def __init__(
self,
files: Union[os.PathLike, Dict[Locale, os.PathLike]],
*,
strict: bool = False,
fallback: Optional[Locale] = None
):
"""
Initialize localization store with translation files.
Parameters:
- files: Path to directory or mapping of locales to file paths
- strict: Whether to raise errors for missing keys
- fallback: Fallback locale when translation missing
"""
@classmethod
def from_directory(
cls,
directory: os.PathLike,
*,
pattern: str = "{locale}.json",
strict: bool = False,
fallback: Optional[Locale] = None
) -> LocalizationStore:
"""
Create store from directory of JSON translation files.
Parameters:
- directory: Directory containing translation files
- pattern: Filename pattern with {locale} placeholder
- strict: Whether to raise errors for missing keys
- fallback: Fallback locale for missing translations
Returns:
Configured LocalizationStore instance
"""
async def reload(self) -> None:
"""Reload all translation files from disk."""
@property
def locales(self) -> Set[Locale]:
"""All available locales in the store."""# Type aliases for localized strings
LocalizedRequired = Union[str, "Localized[str]"]
LocalizedOptional = Union[Optional[str], "Localized[Optional[str]]"]
LocalizationsDict = Union[Dict[Locale, str], Dict[str, str]]
# Alias for British English spelling
Localised = Localizedimport disnake
from disnake.i18n import Localized
# Create localized command name and description
@bot.slash_command(
name=Localized("hello", es="hola", fr="salut"),
description=Localized(
"Say hello to someone",
es="Saluda a alguien",
fr="Dire bonjour à quelqu'un"
)
)
async def hello(
inter: disnake.ApplicationCommandInteraction,
user: disnake.User = disnake.Param(
description=Localized(
"The user to greet",
es="El usuario a saludar",
fr="L'utilisateur à saluer"
)
)
):
await inter.response.send_message(f"Hello {user.mention}!")import disnake
from disnake.i18n import LocalizationStore
from disnake.enums import Locale
# Set up localization store
i18n_store = LocalizationStore.from_directory(
"locales/",
pattern="{locale}.json",
fallback=Locale.en_US
)
# Configure client with localization
bot = disnake.Bot(
command_prefix="!",
intents=disnake.Intents.default(),
localization_provider=i18n_store
)
# Use localization keys in commands
@bot.slash_command(
name="greet",
description=Localized(key="commands.greet.description")
)
async def greet(
inter: disnake.ApplicationCommandInteraction,
target: disnake.User = disnake.Param(
description=Localized(key="commands.greet.target_param")
)
):
# Get localized response message
greeting = await i18n_store.get(
key="messages.greeting",
locale=inter.locale,
username=target.display_name
)
await inter.response.send_message(greeting)Example locales/en-US.json:
{
"commands": {
"greet": {
"description": "Greet another user",
"target_param": "User to greet"
}
},
"messages": {
"greeting": "Hello, {username}!"
}
}Example locales/es.json:
{
"commands": {
"greet": {
"description": "Saluda a otro usuario",
"target_param": "Usuario a saludar"
}
},
"messages": {
"greeting": "¡Hola, {username}!"
}
}Install with Tessl CLI
npx tessl i tessl/pypi-disnake