Mohammad Mahdi Azadjalal
Senior Data Engineer
Translating Your Web Applications Made Easy with Transify
In the realm of web development, supporting multiple languages is crucial for reaching a broader audience. This is where Transify, our Python library, comes into play. It caters to developers aiming to easily add translation capabilities to their applications. Whether you’re using frameworks like FastAPI or Flask, Transify integrates seamlessly, allowing you to manage translations using JSON files efficiently.
Why Choose Transify?
Transify stands out by offering an easy setup for multi-language support. This means you can maintain translation files cleanly without getting bogged down by complex configurations. It’s especially beneficial for web applications that need dynamic, on-the-fly translations.
Key Features
Multiple Language Support
Effortlessly extend your application’s reach by adding translation JSON files for each language. This modular approach keeps your languages organized and manageable.Dynamic Replacements
Transify isn’t just about static text. With dynamic variable insertion, you can create flexible translations that adapt to different contexts.Nested Translation Keys
Organize your translations with nested keys likecaptions.hello, enhancing readability and structure.Locale Switching
Change the active language of your application instantly, providing a personalized experience for each user.Integration with Jinja2 Templates
Utilize real-time translations directly in your HTML templates, enabling a smooth frontend-user experience.
Getting Started with Transify
Installation
You can install Transify using either pip or Poetry, depending on your preference:
Using pip:
pip install transify
Using Poetry:
poetry add transify
Organizing Your Translation Files
Create Language Folders
First, set up a directory namedlangin your project to store translation files.Add Translation Files
Within thelangdirectory, create subfolders for each language code (e.g.,en,fa). Populate these with your translation JSON files.
Example Directory Structure:
lang/
en/
captions.json
messages.json
validations.json
fa/
captions.json
messages.json
validations.json
Sample JSON Translation Files
captions.json
{
"name": "Azadjalal",
"first_name": "First name",
"hello": "Hello",
"goodbye": "Goodbye",
"username": "username",
"good_score": "Good score"
}
messages.json
{
"welcome": "Welcome, :name to my website :website.",
"errors": {
"create": "Create item failed.",
"user": {
"not_found": "The user not found."
}
}
}
validations.json
{
"required": "The :attr is required.",
"between": "The :attr must be between :min and :max values."
}
Integrating Transify into a FastAPI Project
Here’s a complete example of integrating Transify into a FastAPI application:
import pathlib
import uvicorn
from fastapi import FastAPI
from fastapi.requests import Request
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from transify import *
app = FastAPI(title='transify', version='1.0.0')
# Mount static resources
app.mount(
'/resources',
StaticFiles(directory=f'{pathlib.Path(__file__).resolve().parent}/resources', html=False),
name='static'
)
# Jinja2 template setup
templates = Jinja2Templates(
directory=f'{pathlib.Path(__file__).resolve().parent}/resources'
)
# Update the template environment with the trans function
templates.env.globals.update(trans=trans)
def startup():
load_languages(path='tests/lang', default_fallback='en')
app.add_event_handler('startup', startup)
@app.get('/', response_class=HTMLResponse)
async def get_home(request: Request):
return templates.TemplateResponse('home.html', {'request': request, 'lang': get_locale()})
if __name__ == '__main__':
uvicorn.run('test_webapp:app', host='localhost', port=8000, reload=True)
Using Transify in Jinja2 Templates
Embed translations in your HTML templates like this:
<!DOCTYPE html>
<html lang={{ lang }}>
<head>
<title>Transify Example</title>
</head>
<body>
<!-- Example: Display translation for 'hello' -->
<span>{{ trans('captions.hello') }}</span> <!-- Outputs: Hello -->
</body>
<footer>
<!-- Example: Display translation for 'welcome' -->
{{ trans('messages.welcome', 'name:Azadjalal|website:azadjalal.ir') }}
<!-- Outputs: Welcome, Azadjalal to my website azadjalal.ir -->
</footer>
</html>
Core Functions and Methods
load_languages(path: str = 'lang', default_fallback: str = 'en')
Loads translation files from the specified path, setting up different languages and a default fallback.set_locale(locale: str)
Switches the active language to the specified locale, e.g., between ‘en’ and ‘fa’.set_locale('fa')get_locale()
Retrieves the currently active locale.trans(key: str, value: str = None)
Core function for fetching translations. Handles dynamic replacements if a value is provided.# Simple translation trans('captions.hello') # Output: "Hello" # With dynamic replacements trans('messages.welcome', value='name:Azadjalal|website:azadjalal.ir') # Output: "Welcome, Azadjalal to my website azadjalal.ir."
Testing Your Integration
To ensure everything works as expected, use the provided test_transify.py file. This script employs Python’s unittest framework to test key functionalities like language loading, locale switching, and dynamic translations.
Run the tests with:
python test_transify.py
Sample Test Cases
Load Languages
Test that languages are loaded correctly:
self.assertIn('en', lang.languages) self.assertIn('fa', lang.languages)Set Locale
Validate locale switching:
set_locale('fa') self.assertEqual(get_locale(), 'fa') set_locale('en')Basic Translation
Ensure basic translations are accurate:
self.assertEqual(trans('captions.hello'), 'Hello')Dynamic Replacements
Verify translations with dynamic content:
self.assertEqual( trans('validations.between', value='score|min:1|max:20'), 'The score must be between 1 and 20 values.' )Nested Keys
Check translations using nested keys:
self.assertEqual(trans('messages.errors.user.not_found'), 'The user not found.')Locale-Specific Translations
Test different locales:
set_locale('fa') self.assertEqual(trans('captions.hello'), 'سلام')
Error Handling and Customization
Transify elegantly handles missing keys or errors during translation by logging an error and returning the original key as a fallback, safeguarding your application from crashes.
trans('messages.nonexistent') # Returns 'messages.nonexistent'
Customize the load_languages function to fit your directory structure or project setup, allowing flexibility and ease of use.
Conclusion
Transify simplifies the process of managing multiple languages in your web application. With its intuitive setup and robust features for dynamic translations, it seamlessly integrates into Jinja2 templates and various web frameworks. Whether you’re developing with FastAPI or another environment, Transify offers a comprehensive solution for language management.
Explore the source code on GitHub and get started today with Transify to enhance your application’s global reach!