means: A language in Amharic (Ethiopian Language)
Lisan is a Django package that simplifies the process of adding translation support to model fields in Django projects. With Lisan
, you can easily manage multilingual content within your Django models, API, and admin interface.
- Automatic Translation Models: Automatically generate translation models for your fields.
- Flexible Primary Key Configuration: Use either BigInt or UUID as primary keys for translation tables, configurable globally or per model.
- Admin Integration: Seamlessly manage translations through the Django admin interface.
- Fallback Mechanism: Fallback to the default language if a translation is not available.
- Dynamic Getter Methods: Automatically generate methods to access translated fields.
- Pluggable Translation Services: Support for external services like Google Translate to automatically translate content.
- Customizable Admin Display: Configure how translations are displayed in the Django admin interface.
- Flexible Field Types: Add translation support for various field types like
CharField
,TextField
, andJSONField
. - Synchronization of Translatable Fields: Ensures consistency by automatically syncing main model updates with default language translations.
- Installation
- Lisan Settings
- Usage
- API Usage
- Pluggable Translation Services
- Testing Translations
- Contributing
- License
You can install Lisan via pip:
pip install lisan
To start using Lisan
in your project, configure the language settings, middleware, and primary key type (if needed) in your Django settings file.
LISAN_DEFAULT_LANGUAGE = 'en' # Default language for translations
LISAN_ALLOWED_LANGUAGES = ['en', 'am', 'or', 'tg'] # Languages supported by Lisan
LISAN_FALLBACK_LANGUAGES = ['fr', 'es', 'en'] # Customize fallback languages
LISAN_DEFAULT_TRANSLATION_SERVICE = 'yourapp.google_translate_service.GoogleTranslateService' # Pluggable translation service
You can configure Lisan
to use either BigInt
or UUID
as the primary key for translation tables.
To set this globally, use the LISAN_PRIMARY_KEY_TYPE
setting in settings.py
:
from django.db import models
LISAN_PRIMARY_KEY_TYPE = models.UUIDField # Options: models.BigAutoField (default) or models.UUIDField
Alternatively, define lisan_primary_key_type
on specific models to override the global setting.
Make sure to include Lisan
's middleware in your MIDDLEWARE
settings for automatic language detection and management:
MIDDLEWARE = [
...
'lisan.middleware.LanguageMiddleware', # Lisan middleware for handling language preferences
'django.middleware.common.CommonMiddleware',
...
]
To add translation support to a model, simply inherit from LisanModelMixin
and specify which fields should be translatable using the lisan_fields
attribute.
Example:
from django.db import models
from lisan import LisanModelMixin
class Snippet(LisanModelMixin, models.Model):
lisan_fields = ['title', 'description'] # Fields to be translated
title = models.CharField(max_length=100, blank=True, default='')
description = models.TextField(blank=True, default='')
created = models.DateTimeField(auto_now_add=True)
# Optionally specify UUIDField as primary key for translation tables
lisan_primary_key_type = models.UUIDField
class Meta:
ordering = ['created']
Once the model is defined, run the following commands to create and apply migrations:
python manage.py makemigrations
python manage.py migrate
To enable translation management in the Django admin, use LisanAdminMixin
in your admin class.
Example:
from django.contrib import admin
from lisan import LisanAdminMixin
from .models import Snippet
@admin.register(Snippet)
class SnippetAdmin(LisanAdminMixin, admin.ModelAdmin):
list_filter = ('created',)
ordering = ('-created',)
lisan_display_format = "{field_name} ({language_code})" # Customizable admin display format
You can set and get translations using the provided methods.
snippet = Snippet.objects.create(title="Code Snippet Example", description="Example Description")
snippet.set_lisan('am', title="ኮድ ቅርጸት ምሳሌ", description="እንቁ ምሳሌ")
You can retrieve translations with a fallback mechanism or even auto-translate content using an external service.
amharic_title = snippet.get_lisan_field('title', 'am', auto_translate=True)
print(amharic_title) # Output: ኮድ ቅርጸት ምሳሌ (if available) or the auto-translated version
english_title = snippet.get_lisan_field('title', 'en')
print(english_title) # Output: Code Snippet Example
When updating translatable fields directly in the main model, Lisan ensures synchronization with the default language translation automatically.
Request:
PATCH /api/snippets/1/
Accept-Language: en
Content-Type: application/json
{
"title": "Updated Snippet Title"
}
Behavior:
- Updates the
title
field in the main model. - Synchronizes the updated value with the
en
translation.
Response:
{
"id": 1,
"title": "Updated Snippet Title",
"translations": [
{
"language_code": "en",
"title": "Updated Snippet Title",
"description": "Existing description"
},
{
"language_code": "am",
"title": "ኮድ ቅርጸት ምሳሌ",
"description": "እንቁ ምሳሌ"
}
]
}
Here is how to use the API to create and retrieve a translated snippet.
To create a snippet with translations, send a POST
request to the appropriate API endpoint with the following payload:
Request Body:
{
"title": "Code Snippet Example",
"description": "Example Description",
"translations": [
{
"language_code": "am",
"title": "ኮድ ቅርጸት ምሳሌ",
"description": "እንቁ ምሳሌ"
}
]
}
To retrieve translations for a snippet, use the TranslationSerializer
to structure the translations in a nested format.
Request Example:
GET /api/snippets/1/
Accept-Language: am
The response will include all translations for the snippet in a structured format:
Response Example:
{
"id": 1,
"title": "Code Snippet Example",
"description": "Example Description",
"translations": [
{
"language_code": "am",
"title": "ኮድ ቅርጸት ምሳሌ",
"description": "እንቁ ምሳሌ"
},
{
"language_code": "en",
"title": "Code Snippet Example",
"description": "Example Description"
}
]
}
You can dynamically handle user preferences for translations based on the Accept-Language
header or custom user settings.
class SnippetSerializer(LisanSerializerMixin, serializers.ModelSerializer):
class Meta:
model = Snippet
fields = ['id', 'title', 'description']
def to_representation(self, instance):
representation = super().to_representation(instance)
request = self.context.get('request')
language_code = request.headers.get('Accept-Language', 'en')
representation['title'] = instance.get_lisan_field('title', language_code)
return representation
The Lisan
package supports pluggable translation services, allowing you to integrate with third-party APIs like Google Translate for automatic translations. You can configure this via the LISAN_DEFAULT_TRANSLATION_SERVICE
setting.
You can create custom translation services by implementing the BaseTranslationService
class.
Example using Google Translate:
# google_translate_service.py
from googletrans import Translator
from lisan.translation_services import BaseTranslationService
class GoogleTranslateService(BaseTranslationService):
def __init
__(self):
self.translator = Translator()
def translate(self, text, target_language):
return self.translator.translate(text, dest=target_language).text
To configure your application to use this service, simply set it in the LISAN_DEFAULT_TRANSLATION_SERVICE
setting in settings.py
:
LISAN_DEFAULT_TRANSLATION_SERVICE = 'yourapp.google_translate_service.GoogleTranslateService'
To ensure that your translations are handled correctly, here’s an example of how you can write tests for translated fields:
from django.test import TestCase
from .models import Snippet
class SnippetTestCase(TestCase):
def setUp(self):
self.snippet = Snippet.objects.create(title="Hello World", description="Description Example")
def test_translation_set(self):
self.snippet.set_lisan('fr', title="Bonjour le monde", description="Exemple de description")
self.assertEqual(self.snippet.get_lisan_field('title', 'fr'), "Bonjour le monde")
def test_fallback(self):
# Test that it falls back to English if no French translation is available
self.assertEqual(self.snippet.get_lisan_field('title', 'fr'), "Hello World")
This testing structure ensures that your translations work as expected, using both direct translations and fallback mechanisms when translations are unavailable.
If you find any issues or have suggestions for improvements, feel free to open an issue or submit a pull request on GitHub. Contributions are always welcome.
Lisan is licensed under the MIT License. See the LICENSE file for more information.