Skip to content

It's a lightweight Python package designed to facilitate seamless translation for multilingual websites

License

Notifications You must be signed in to change notification settings

azadjalal/transify

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Transify: A Multi-Language Translator for Web Applications

Transify is a Python library designed for easy integration of multi-language translation functionality in web applications. It allows you to use custom translation files (in JSON format) for various languages and locales. This tool is ideal for web frameworks like FastAPI, Flask, or any other platform where dynamic translations are necessary.

Features

  • Multiple Language Support: Add and manage different languages by simply providing JSON files for each language.
  • Dynamic Replacements: Supports dynamic replacements like variable insertion into translated strings.
  • Nested Translation Keys: Allows translation via nested keys (e.g., captions.hello).
  • Locale Switching: Switch between different locales on-the-fly.
  • Works with Jinja2 Templates: Easily integrate with Jinja2 templates for real-time translations in your web pages.

Installation

You can install transify via pip or poetry:

Using pip:

pip install transify

Using poetry:

poetry add transify

Setting Up Translations

  1. Create Language Folders: In your project, create a folder named lang to hold your translation files.

  2. Add Translation Files: Inside the lang folder, create subdirectories for each language (e.g., en, fa) and add the respective translation JSON files.

Example structure:

lang/
  en/
    captions.json
    messages.json
    validations.json
  fa/
    captions.json
    messages.json
    validations.json
  ...

Example JSON Files

Below are examples of the translation files in JSON format:

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."
}

Using Transify in a Project

Here’s an example of how you can integrate transify into a FastAPI project:

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)

Then in your Jinja2 templates, you can use the translations 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>

Functions and Methods

load_languages(path: str = 'lang', default_fallback: str = 'en')

oads translation files from the given path and sets up the languages. If a language file is missing, it falls back to the default_fallback language (usually 'en').

set_locale(locale: str)

Sets the active locale to the desired language. For example, you can switch between "en" (English) and "fa" (Farsi) by calling:

set_locale('fa')

get_locale()

Returns the current active locale.

trans(key: str, value: str = None)

This is the core translation function. It takes the key (e.g., captions.hello) and looks up the corresponding translation in the active language files. If a value is provided, it performs dynamic replacements.

  • For simple translation:
trans('captions.hello')  # Output: "Hello"
  • For translations with dynamic replacements (using : syntax):
trans('messages.welcome', value='name:Azadjalal|website:azadjalal.ir')  
# Output: "Welcome, Azadjalal to my website azadjalal.ir."

Testing the Library

We have included a test_transify.py file to help you verify the functionality of the library. It uses Python’s unittest framework and covers various scenarios such as loading languages, setting locales, basic translations, dynamic replacements, and nested keys.

python test_transify.py

Sample Test Cases in test_transify.py

  1. Load Languages Test if the languages are correctly loaded:
self.assertIn('en', lang.languages)
self.assertIn('fa', lang.languages)
  1. Set Locale Test switching between locales:
set_locale('fa')
self.assertEqual(get_locale(), 'fa')
set_locale('en')
  1. Basic Translation Test basic translations:
self.assertEqual(trans('captions.hello'), 'Hello')
  1. Dynamic Replacements Test translations with dynamic replacements:
self.assertEqual(
    trans('validations.between', value='score|min:1|max:20'),
    'The score must be between 1 and 20 values.'
)
  1. Nested Keys Test translations with nested keys:
self.assertEqual(trans('messages.errors.user.not_found'), 'The user not found.')
  1. Locale-Specific Translations Test translations in different locales:
set_locale('fa')
self.assertEqual(trans('captions.hello'), 'سلام')

Error Handling

If a key is missing or there’s an error during the translation process, the library will log an error and return the original key as a fallback. For example:

trans('messages.nonexistent')  # Returns 'messages.nonexistent'

Customization

You can customize the load_languages function to load translations from any directory structure or path you prefer. This makes it easy to fit into different project setups.

Conclusion

With transify, you can easily manage multi-language support in your web application, with simple setup, dynamic translations, and seamless integration into Jinja2 templates. Whether you’re working with FastAPI or another web framework, this library provides everything you need for language management.

About

It's a lightweight Python package designed to facilitate seamless translation for multilingual websites

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published