Setting up
Start by downloading the package via pip.
python3 -m pip install discord-localization
After that, you can just import it into your file as a discord.py extension.
Examples
from discord.ext import localization
import random
_ = localization.Localization("main.i18n.json", "en")
# the first option is the relative path to the localization
# file. the second is the fallback/default language that is
# used if the actual language is not found.
dice = random.randint(1, 6)
language = input("What's your native language? / Was ist Deine Muttersprache? (en/de) >>> ")
print(_("dice_result", language, dice=dice))
{
"en": {
"dice_result": "Your dice rolled {dice}!"
},
"de": {
"dice_result": "Dein Würfel hat eine {dice} gewürfelt!"
}
}
Integrating it into your Discord bot
import discord
from discord.ext import commands, localization
bot = commands.Bot(command_prefix="!", intents=discord.Intents.all())
# hey guys, breaking the 4th wall here. please stop using Intents.default()
# just to set the message_contentintent to True right after. Intents.all() does
# it for you.
_ = localization.Localization("main_localization.json", "en")
@bot.event
async def on_ready():
print("Bot is ready!")
@bot.command()
async def ping(ctx):
await ctx.reply(_("ping", ctx, latency=bot.latency * 1000))
{
"en": {
"ping": "Pong! {latency}ms"
},
"en-US": {
"ping": "Pong! {latency}ms, but American! (because Discord makes a difference between en-US and en-UK locales - you can circumvent this by setting the default_locale)"
},
"en-UK": {
"ping": "Ping is {latency}ms, innit, bruv? (i'm sorry)"
},
"fr": {
"ping": "Bonjour! Ping is {latency}ms!"
}
}
Explanation:
- By setting the default locale to "en", we won't have any issues with unfinished localizations. This way, we are also not required to define localizations for both "en-US" and"en-UK" (since Discord's API differentiates them, however, usually, bots don't.)
- We are passing a
latencyargument to the localization function (which is also available withLocalization._! But calling the object is fine too.), which will be later usedwhenever we use{latency}in a localization. - We are defining an
enlocale in the JSON file, even though both Discord's API and discord.py doesn't have such a locale. This is to make it more obvious that everything inthat locale should be in English - you could also name itdefault_locale, you just have to make sure to edit it in theLocalizationobject. - We pass
ctxto the localization function, which will automatically try gettingctx.guild.preferred_locale. This works withInteraction(by usingInteraction.guildpreferred_localeinternally),Guild(by usingguild.preferred_localeinternally), or just passing theLocaleitself, for example,discord.Locale.american_english(whichwill convert to theen-USlocale).
Working with plurals
from discord.ext.localization import Localization
import locale
_ = Localization("main_plurals.json") # this will look for main_plurals.json as the language JSON file
apples = int(input("How many apples do you have? >>> "))
language = locale.getlocale()[0][:2] # this will return the default OS language, such as en, hu, de, fr, es etc.
print(_.one("apples", apples, language, apples=apples))
{
"en": {
"apples": ["You only have one apple! What a loser...", "You have {apples} apples!"]
},
"hu": {
"apples": ["{apples} almád van!"]
}
}
This example does a great job at presenting how the .one() function works. Here's the explanation for the code:
The code will look for the default OS language, and will tell you how many apples you have with plurals in mind. I always get angry when I see "you have 1 apples"-ish text on awebsite, and it's an easy fix, but for some reason, many developers don't pay attention to it.
Hungarian doesn't make a difference between plurals, so the list for "hu"/"apples" only has 1 item. This won't be a problem though - the library isn't hardcoded to only look forthe first and second elements in the returned list, it will look for the first and the last. Which means that if a list only has 1 item, it will only return that item.
Advanced usage with nested keys and nested objects
With v1.1.0, we now have the ability to do some nesting with the dictionaries.
For example, now that we've learned how to work with plurals, we can also work with nested keys. Here's an example of a nested JSON file:
{
"en": {
"apples": {
"one": "You only have one apple! What a loser...",
"three": "You have three apples! That's a lot!",
"many": "You have {apples} apples!"
}
},
"hu": {
"apples": {
"one": "{apples} almád van!",
"three": "Három almád van! Ez nagyon sok!",
"many": "Van {apples} almád!"
}
}
}
We may now use the localize() method to get the nested keys, with the text argument being a "path" to our string, seperated by dots. Here's an example:
from discord.ext.localization import Localization
_ = Localization("nested.json")
apples = int(input("How many apples do you have? >>> "))
locale = input("What's your locale? >>> ")
if apples == 1:
print(_.localize("apples.one", "one", apples=apples))
# you could use an f-string here, but I'm trying to keep it simple
elif apples == 3:
print(_.localize("apples.three", "three", apples=apples))
else:
print(_.localize("apples.many", "many", apples=apples))
Metadata
Release files for discord-localization 1.1.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| discord_localization-1.1.5.tar.gz | 11.3 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| discord_localization-1.1.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 20.0 kB
Release files / discord_localization-1.1.5.tar.gz
| Download URL | discord_localization-1.1.5.tar.gz |
|---|---|
| Size | 11.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
17af16ec094b7fb33d73f8e28068eed32f1364dc1aca65132481a208050bbefa
|
|
BLAKE2b-256 checksum How to use checksums |
dabec4c8904a2bf30c621eaae2762e1bd195d0480c01375504f73c2789b7e913
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 2, 2026.
Transparency logRelease files / discord_localization-1.1.5-py3-none-any.whl
| Download URL | discord_localization-1.1.5-py3-none-any.whl |
|---|---|
| Size | 8.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3dd2f61c2caa10b886296d95d62fb36ae1079247ef348136783d223ec9ab93fb
|
|
BLAKE2b-256 checksum How to use checksums |
0274d0525342c7d3bd9e2c252c6eee95e38e17acbd6c24f88ac8b035dcbbd9b7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 2, 2026.
Transparency logSecurity for discord-localization 1.1.5
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for discord_localization-1.1.5.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 2, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.