How Voice-Pro Implements Internationalization (i18n): A Complete Technical Guide

Voice-Pro implements a lightweight, runtime internationalization system using a custom I18nAuto class that loads locale-specific JSON dictionaries and exposes a callable interface for translating UI strings without external dependencies.

Voice-Pro, an open-source AI voice processing application, handles multilingual support through a custom-built internationalization (i18n) layer that operates entirely at runtime. Unlike frameworks that rely on heavy external libraries such as Babel or gettext, the repository uses a simple JSON-based approach located in src/i18n/. This implementation enables rapid addition of new languages while keeping the application footprint minimal.

Core Architecture of the Voice-Pro i18n System

The internationalization layer consists of three primary components working in concert: a callable loader class, JSON translation bundles, and an AST-based key scanner.

The I18nAuto Callable Class (src/i18n/i18n.py)

At the heart of the system is the I18nAuto class, which implements Python's __call__ method to behave like a function. When instantiated, it determines the target locale, loads the corresponding JSON file, and stores the translation mapping in self.language_map.

from src.i18n.i18n import I18nAuto

i18n = I18nAuto(language="ko_KR")
print(i18n("Upload media"))  # Returns: "미디어 업로드"

The __call__ method performs a simple dictionary lookup, returning the translated value or the original key if no translation exists:

def __call__(self, key):
    return self.language_map.get(key, key)

Locale Detection and Fallback Strategy

When I18nAuto() receives "Auto" or None as the language parameter, it queries the system locale using locale.getdefaultlocale()[0]. If the resolved locale lacks a corresponding JSON file in src/i18n/locale/, the system gracefully falls back to en_US.


# From src/i18n/i18n.py

if language in ["Auto", None]:
    language = locale.getdefaultlocale()[0]
json_path = os.path.join(Path(__file__).resolve().parent, f"locale/{language}.json")
if not os.path.exists(json_path):
    language = "en_US"

JSON Translation Bundles (src/i18n/locale/)

Translations reside in flat JSON files named by locale code (e.g., en_US.json, ko_KR.json, ja_JP.json). Each file contains a single dictionary mapping English source strings to localized equivalents:

{
    "Language": "언어",
    "Upload media": "미디어 업로드",
    "Submit": "제출"
}

The load_language_list() function reads these files with UTF-8 encoding to support multilingual character sets.

Runtime Translation Workflow

The Voice-Pro i18n system operates through a three-stage pipeline that executes whenever the application launches or switches languages.

  1. Initialization: I18nAuto instantiates and resolves the target locale via locale.getdefaultlocale() or a user-specified parameter.

  2. Loading: The constructor calls load_language_list(language), which constructs a path to src/i18n/locale/{language}.json and deserializes the contents into self.language_map.

  3. Resolution: UI modules call i18n("Key String"), triggering __call__ to return the mapped value or the key itself as a fallback.

This approach ensures that adding support for a new language requires only creating a new JSON file and restarting the application.

Automated Key Discovery with scan_i18n.py

Maintaining translation consistency across a growing codebase requires knowing exactly which strings require translation. The src/i18n/scan_i18n.py utility automates this by parsing the abstract syntax tree (AST) of every Python file in the repository.

The scanner walks the source tree, identifies all calls to the i18n() function, and extracts the string literals passed as arguments. This produces the canonical list of source-language keys that must exist in every locale file.


# Simplified logic from src/i18n/scan_i18n.py

for filename in python_files:
    tree = ast.parse(open(filename).read())
    i18n_strings = extract_i18n_strings(tree)
    # Collects every string passed to i18n(...)

Developers run this script during the build process to generate translation templates or verify that all UI strings are accounted for in the locale files.

UI Integration in Gradio Components

Voice-Pro uses Gradio for its web interface, and every user-visible string passes through the i18n callable. The pattern appears consistently across UI modules such as app/tab_tts_kokoro.py and app/tab_vsr.py.


# From app/tab_tts_kokoro.py

from src.i18n.i18n import I18nAuto
i18n = I18nAuto()

gr.Dropdown(
    label=i18n("Language"),
    choices=kokoro_voice.gradio_languages(),
    value=kokoro_voice.selected_language
)

Because i18n evaluates at render time, switching the locale and reloading the interface immediately reflects the new language without code changes.

Adding a New Language to Voice-Pro

Extending Voice-Pro to support additional languages follows a straightforward process that leverages the existing scanner utility.

First, run the scanner to collect all current translation keys:

python src/i18n/scan_i18n.py

Next, create a new JSON file in src/i18n/locale/ using the locale code as the filename (e.g., de_DE.json for German). Copy the collected keys and provide translations:

{
    "Language": "Sprache",
    "Upload media": "Medien hochladen",
    "Submit": "Absenden"
}

Finally, instantiate I18nAuto with the new locale code or set the system locale accordingly. The application loads the new translations immediately upon restart.

Summary

  • Voice-Pro uses a custom I18nAuto class in src/i18n/i18n.py that loads JSON dictionaries and acts as a callable translation function.
  • Locale detection relies on locale.getdefaultlocale() with a hard fallback to en_US when translation files are missing.
  • Translation bundles are flat JSON files stored in src/i18n/locale/, requiring no compilation or external dependencies.
  • scan_i18n.py parses the AST to extract all i18n() calls, ensuring translation keys remain synchronized with the codebase.
  • UI modules import a single i18n instance and wrap all labels, enabling real-time language switching in Gradio components.

Frequently Asked Questions

Does Voice-Pro use external i18n libraries like Babel or gettext?

No. According to the Voice-Pro source code, the implementation avoids external dependencies by using a lightweight, custom-built system. The I18nAuto class in src/i18n/i18n.py handles all translation logic through standard library modules (json, locale, pathlib) and simple dictionary lookups.

How does Voice-Pro handle missing translations?

The system implements a key fallback mechanism. When i18n("Key") is called, the __call__ method executes self.language_map.get(key, key), returning the original English key if no translation exists in the loaded JSON file. This ensures the UI remains functional even with incomplete locale files.

Where are the translation files located in the repository?

All translation bundles reside in the src/i18n/locale/ directory. Each language has its own JSON file named with the standard locale code (e.g., en_US.json, ko_KR.json). The core loader logic is located in src/i18n/i18n.py, while the development utility src/i18n/scan_i18n.py manages key discovery.

How can developers add support for a new language?

Developers must create a new JSON file in src/i18n/locale/ named with the appropriate locale code, then run python src/i18n/scan_i18n.py to collect all required translation keys from the source code. After populating the JSON file with translations, the language becomes available by passing the locale code to I18nAuto(language="xx_XX") or setting the system locale.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →