Skip to main content

A lightweight Python package designed to facilitate seamless translation for multilingual websites.

Project description

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

transify-1.0.0.tar.gz (6.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

transify-1.0.0-py3-none-any.whl (6.6 kB view details)

Uploaded Python 3

File details

Details for the file transify-1.0.0.tar.gz.

File metadata

  • Download URL: transify-1.0.0.tar.gz
  • Upload date:
  • Size: 6.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.8.20

File hashes

Hashes for transify-1.0.0.tar.gz
Algorithm Hash digest
SHA256 dc42778fc5f8f76c401a0e2c27b0f68be45961c2cb9c4942a2e9e6ab043fcaea
MD5 ab224c40e6150a191837f76eda7d44f6
BLAKE2b-256 f42e992b0a466038d00f2f3fdef1803f674576f9b77ba801d88408033333cd8c

See more details on using hashes here.

File details

Details for the file transify-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: transify-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 6.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.8.20

File hashes

Hashes for transify-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 00efcf205b77070670541c5504c27e63e7f35dc8364ebc44bb714ba72acda05a
MD5 29669c33d8c1ff29a3e6e9bce40e6518
BLAKE2b-256 ec18c14e860123ad4d77ca7c04347917d8a4802273f11c1ac93e64242932d65a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page