Skip to main content

PyPI Python 3.6 Python 3.7 t

Tradukoj

Tradujok is a django db-based translation system with IETF's BCP 47 standard support and django-rest-framework serializers.

Tradukoj can be integrated with common js i18n libs thanks to his JSON tree generation feature.

This app is maintained and internally used by Develatio Technologies.

Requierements

  • Python: >= 3.6

  • Django: >= 2.1, 2.2

Features

  • Namespaces to separate projects or big sections of your app
  • JSON tree generation with your translations
  • django-rest-framework urls/views/serializers
  • django-rest-framework fields to be used in serializers
  • Fallback translation for drf fields
  • Translate model fields
  • Languaje detection endpoint
  • RTL - LTR support
  • PO files Import/Export
  • Public/Private translations isolation

Quick start

  1. Install pip install django-tradukoj

  2. Add "tradukoj" to INSTALLED_APPS:

INSTALLED_APPS = {
    ...
    'tradukoj'
}
  1. Include the tradukoj URLconf in urls.py: url(r'^tradukoj/', include('tradukoj.urls'))

  2. Run python manage.py migrate to create db records.

Translate model fields

Usage of OneToOneTradukojField:

from tradukoj.fields import OneToOneTradukojField

class MyModel(models.Model):
    name = OneToOneTradukojField(null=True, blank=True, verbose_name='Name')

Handle translations

Automatic key generation:

>>> from tradukoj.models import TranslationKey
>>> from myapp.models import MyModel

>>> instance = MyModel()
>>> # This creates a translatable key with automatically generated name
>>> instance.name = TranslationKey(init_namespace='mynamespace', public=True)
>>> instance.name
<TranslationKey: mynamespace.myapp_mymodel_name_0def4d78080144cdbc96302842935192>

>>> # This will add a translation for es-ES to instance.name
>>> # A record with 'es-ES' into tradukoj.models.BCP47 will be created if it
>>> # does not exist.
>>> instance.name.translate('es-ES', 'mi nombre')

>>> # Access translations:
>>> instance.name.translations.all()
<QuerySet [<Translation: (es-ES - español (Spanish)) mynamespace.myapp_mymodel_name_0def4d78080144cdbc96302842935192 => mi nombre>]>

>>> instance.name.translations.get(bcp47__langtag='es-ES')
<Translation: (es-ES - español (Spanish)) test.medicalscience_specialties_name_0def4d78080144cdbc96302842935192 => mi nombre>

>>> instance.name.translations.get(bcp47__langtag='es-ES').str_translation()
'mi nombre'

Custom key name:

If you dont specify a key for translation, a random one will be generated. To specify a key, you should pass it as argument to TranslationKey:

>>> instance.name = TranslationKey(init_namespace='test', text='A translatable string', public=True)
>>> instance.name
<TranslationKey: test.A translatable string>
>>> instance.name.save()
>>> instance.name.translate('es-ES', 'Una cadena traducible')
>>> instance.name.translations.all()
<QuerySet [<Translation: (es-ES - español (Spanish)) test.A translatable string => Una cadena traducible>]>

JSON tree of translations

If you are planning to use json tree feature of tradukoj, remember that a dot in key are handled as subobject.

TranslationKey(init_namespace='project', text='home.title', public=True)
TranslationKey(init_namespace='project', text='home.subtitle', public=True)

results into this json object:

{
    es-ES: {
        project: {
            home: {
                title: 'Bienvenido',
                subtitle: 'Secciones'
            }
        }
    },
    en-US: {
        project: {
            home: {
                title: 'Welcome',
                subtitle: 'Sections'
            }
        }
    }
}

API REST Endpoints

  • Languaje detection: YOUR_API_URL/tradukoj/bestlangtag/ Asking from es-ES;en (spanish-Spain,english) a web with only es-MX (spanish-Mexico) lang:
[
    {
        "langtag": "es-MX",
        "score":92,
        "accept_lang": "es-es"
    },
    {
        "langtag": "es-MX",
        "score": 92,
        "accept_lang":"es"
    },
    {
        "langtag":"en",
        "score":100,
        "accept_lang":"en"
    }
]
  • Available langs: YOUR_API_URL/tradukoj/available/
{
    "count": 28,
    "next": null,
    "previous": null,
    "results": [
        {"langtag":"en-EN","name":"English (English)","best_match_score":92,"default":false,"direction":0},
        {"langtag":"es-MX","name":"español (Spanish)","best_match_score":92,"default":false,"direction":0},
        {"langtag":"en-US","name":"English (English)","best_match_score":98,"default":false,"direction":0},
        {"langtag":"ar-LB","name":"العربية (Arabic)","best_match_score":0,"default":false,"direction":1},
        {"langtag":"fr-FR","name":"français (French)","best_match_score":0,"default":false,"direction":0},
        {"langtag":"pt-PT","name":"português (Portuguese)","best_match_score":0,"default":false,"direction":0},
        {"langtag":"ru-RU","name":"русский (Russian)","best_match_score":0,"default":false,"direction":0},
        {"langtag":"de-DE","name":"Deutsch (German)","best_match_score":0,"default":false,"direction":0},
        {"langtag":"it-IT","name":"italiano (Italian)","best_match_score":0,"default":false,"direction":0},
        {"langtag":"hu-HU","name":"magyar (Hungarian)","best_match_score":0,"default":false,"direction":0},
        {"langtag":"cs-CZ","name":"čeština (Czech)","best_match_score":0,"default":false,"direction":0},
        {"langtag":"zh-CN","name":"中文 (Chinese)","best_match_score":0,"default":false,"direction":0},
        {"langtag":"vi-VN","name":"Tiếng Việt (Vietnamese)","best_match_score":0,"default":false,"direction":0},
        {"langtag":"hi-IN","name":"हिन्दी (Hindi)","best_match_score":0,"default":false,"direction":0},
        {"langtag":"uk_UA","name":"українська (Ukrainian)","best_match_score":0,"default":false,"direction":0},
        {"langtag":"hy_AM","name":"հայերեն (Armenian)","best_match_score":0,"default":false,"direction":0},
        {"langtag":"be_BY","name":"беларуская (Belarusian)","best_match_score":0,"default":false,"direction":0},
        {"langtag":"bg_BG","name":"български (Bulgarian)","best_match_score":0,"default":false,"direction":0},
        {"langtag":"km_KH","name":"ខ្មែរ (Khmer)","best_match_score":84,"default":false,"direction":0},
        {"langtag":"et_EE","name":"eesti (Estonian)","best_match_score":0,"default":false,"direction":0},
        {"langtag":"lv_LV","name":"latviešu (Latvian)","best_match_score":0,"default":false,"direction":0},
        {"langtag":"pl_PL","name":"polski (Polish)","best_match_score":0,"default":false,"direction":0},
        {"langtag":"ro_RO","name":"română (Romanian)","best_match_score":0,"default":false,"direction":0},
        {"langtag":"uz_Latn","name":"o‘zbek (Uzbek)","best_match_score":0,"default":false,"direction":0},
        {"langtag":"tr_TR","name":"Türkçe (Turkish)","best_match_score":0,"default":false,"direction":0},
        {"langtag":"th_TH","name":"ไทย (Thai)","best_match_score":0,"default":false,"direction":0},
        {"langtag":"zh_TW","name":"中文 (Chinese)","best_match_score":0,"default":false,"direction":0},
        {"langtag":"az_AZ","name":"azərbaycan (Azerbaijani)","best_match_score":0,"default":false,"direction":0},
    ]
}
  • Get all public translations list: YOUR_API_URL/tradukoj/public/
  • Get all private translations list: YOUR_API_URL/tradukoj/private/
  • Get plain JSON of all public translations: YOUR_API_URL/tradukoj/public/plain/
  • Get plain JSON of all private translations: YOUR_API_URL/tradukoj/private/plain/
  • Get filtered public translations: YOUR_API_URL/tradukoj/public/plain/?bcp47__langtag=es&key__namespace__text=mynamespace
  • Get filtered private translations: YOUR_API_URL/tradukoj/public/plain/?bcp47__langtag=es&key__namespace__text=mynamespace

Django Rest Framework, Tradukoj Field.

To handle a model translatable field into your drf serializers, TradukojSerializedField

from tradukoj.drf_fields import TradukojSerializedField

class MySerializer(serializers.ModelSerializer):
    name = TradukojSerializedField(read_only=True, fallback_langtag='en-US')

    class Meta:
        model = MyModel
        exclude = ('id', )

This will give you a JSON like:

{
    name: {
        'fallback': 'Welcome',
        'text': 'mykey',
        'translations': {
            'es-ES': 'Bienvenido',
            'en-US': 'Welcome'
        }
    }
}

Command line tools

Generate .po file

usage: manage.py generate_pofile [-h] --langtag LANGTAG --output OUTPUT
                                 --namespace NAMESPACE --reference_langtag
                                 REFERENCE_LANGTAG [--version] [-v {0,1,2,3}]
                                 [--settings SETTINGS]
                                 [--pythonpath PYTHONPATH] [--traceback]
                                 [--no-color] [--force-color]

Generate a .po file of langtag

optional arguments:
  -h, --help            show this help message and exit
  --langtag LANGTAG     tag used in BCP47
  --output OUTPUT       output file
  --namespace NAMESPACE
                        namespace of translations
  --reference_langtag REFERENCE_LANGTAG
                        translated text used in comments to help translator
                        team
  --version             show program's version number and exit
  -v {0,1,2,3}, --verbosity {0,1,2,3}
                        Verbosity level; 0=minimal output, 1=normal output,
                        2=verbose output, 3=very verbose output
  --settings SETTINGS   The Python path to a settings module, e.g.
                        "myproject.settings.main". If this isn't provided, the
                        DJANGO_SETTINGS_MODULE environment variable will be
                        used.
  --pythonpath PYTHONPATH
                        A directory to add to the Python path, e.g.
                        "/home/djangoprojects/myproject".
  --traceback           Raise on CommandError exceptions
  --no-color            Don't colorize the command output.
  --force-color         Force colorization of the command output.

Generate a .po file of es-ES and put en-US translations as a commentary of every msgid:

python manage.py generate_pofile --langtag es-ES --output ./pofile.po --namespace mynamespace --reference_langtag en-US

Destroy keys not in a .po file:

This will destroy those keys not in a .po file and related translations.

usage: manage.py destroy_dbkeys_not_in_pofile [-h] --pofile POFILE --namespace
                                              NAMESPACE [--safe] [--version]
                                              [-v {0,1,2,3}]
                                              [--settings SETTINGS]
                                              [--pythonpath PYTHONPATH]
                                              [--traceback] [--no-color]
                                              [--force-color]

Remove those translations key in DB that does not exists in a given pofile

optional arguments:
  -h, --help            show this help message and exit
  --pofile POFILE       The pofile
  --namespace NAMESPACE
                        The namespace
  --safe                Show those keys that should be deleted but do not
                        commit delete command on db
  --version             show program's version number and exit
  -v {0,1,2,3}, --verbosity {0,1,2,3}
                        Verbosity level; 0=minimal output, 1=normal output,
                        2=verbose output, 3=very verbose output
  --settings SETTINGS   The Python path to a settings module, e.g.
                        "myproject.settings.main". If this isn't provided, the
                        DJANGO_SETTINGS_MODULE environment variable will be
                        used.
  --pythonpath PYTHONPATH
                        A directory to add to the Python path, e.g.
                        "/home/djangoprojects/myproject".
  --traceback           Raise on CommandError exceptions
  --no-color            Don't colorize the command output.
  --force-color         Force colorization of the command output.

Show incompatible keys when use JSON tree generation feature

If you are planning to use JSON tree generation, some keys will be incompatible with this scheme:

  • namespace.section.title = 'test'
  • namespace.section = 'test'

to detect those incompatibility, use show_incompatible_tree_key command:

usage: manage.py show_incompatible_tree_key [-h] [--pofile POFILE] [--version]
                                            [-v {0,1,2,3}]
                                            [--settings SETTINGS]
                                            [--pythonpath PYTHONPATH]
                                            [--traceback] [--no-color]
                                            [--force-color]

Show incompatible Translation Key for plain tree generation

optional arguments:
  -h, --help            show this help message and exit
  --pofile POFILE       Test pofile instead database
  --version             show program's version number and exit
  -v {0,1,2,3}, --verbosity {0,1,2,3}
                        Verbosity level; 0=minimal output, 1=normal output,
                        2=verbose output, 3=very verbose output
  --settings SETTINGS   The Python path to a settings module, e.g.
                        "myproject.settings.main". If this isn't provided, the
                        DJANGO_SETTINGS_MODULE environment variable will be
                        used.
  --pythonpath PYTHONPATH
                        A directory to add to the Python path, e.g.
                        "/home/djangoprojects/myproject".
  --traceback           Raise on CommandError exceptions
  --no-color            Don't colorize the command output.
  --force-color         Force colorization of the command output.

Load .po files

Importing tradukoj.admin models into your admin, will give you some features like importing .po files.

from tradukoj import models


class TranslationKeyAdmin(admin.ModelAdmin):
    search_fields = ('text',)

class TranslationAdmin(admin.ModelAdmin):
    search_fields = ('key__text',)


admin.site.register(models.TranslationKey, TranslationKeyAdmin)
admin.site.register(models.GetTextFile)
admin.site.register(models.Namespace)
admin.site.register(models.Translation, TranslationAdmin)
admin.site.register(models.BCP47)

Vue.js: Translate fields POC

Assuming that you are storing your current languaje tag in store.state.i18n.active_langtag, use this POC vuejs code:

create a plugins/tradukoj-translate.js with this content:

import store from "../store";

const TradukojTranslatable = {
  install(Vue) {
    Vue.mixin({
      methods: {
        $tradukojTranslate(translatable) {
          if (!translatable) {
            return "";
          }

          if (
            translatable.translations &&
            translatable.translations[store.state.i18n.active_langtag]
          ) {
            return translatable.translations[
              store.state.i18n.active_langtag
            ];
          }

          if (translatable.fallback) {
            return translatable.fallback;
          }

          return "";
        }
      }
    });
  }
};
export default TradukojTranslatable;

Register globally:

import TradukojTranslatable from "@/plugins/tradukoj-translatable";
Vue.use(TradukojTranslatable);

Use in component:

<template>
  <div>
    <p>{{ $tradukojTranslate(mymodel.name) }}</p>
  </div>
</template>
[...]

Once you change the value of store.state.i18n.active_langtag, the translations will be automatically updated to current selected lang.

Metadata

Release files for django-tradukoj 1.2.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-tradukoj 1.2.4
File Size Uploaded Provenance
django-tradukoj-1.2.4.tar.gz 17.7 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for django-tradukoj 1.2.4
File Interpreter ABI Platform
django_tradukoj-1.2.4-py2-none-any.whl Python 2 none any Details

Total release size: 45.4 kB

Release files / django-tradukoj-1.2.4.tar.gz

Download URL django-tradukoj-1.2.4.tar.gz
Size 17.7 kB
Tags Source
SHA-256 checksum
How to use checksums
7338a3b1a7b01e6e67590beaaa0b294e2f3714da698bad68d3f7f27187f5fd32
BLAKE2b-256 checksum
How to use checksums
3636c40dd08ecfe249bd437fad379347a6060a0a78b6e78924d9760a96da0067
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.12.1 pkginfo/1.4.2 requests/2.23.0 setuptools/46.0.0 requests-toolbelt/0.9.1 tqdm/4.28.1 CPython/3.7.7

Release files / django_tradukoj-1.2.4-py2-none-any.whl

Download URL django_tradukoj-1.2.4-py2-none-any.whl
Size 27.7 kB
Tags Python 2
SHA-256 checksum
How to use checksums
34886ea75e209822e6ab96186ceb0634c72e10a8063c07395e304c8818fb8aff
BLAKE2b-256 checksum
How to use checksums
3e8da2100ca7f8f85fb4ff51430def9195ca799d8790611af515992876f66eff
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.12.1 pkginfo/1.4.2 requests/2.23.0 setuptools/46.0.0 requests-toolbelt/0.9.1 tqdm/4.28.1 CPython/3.7.7

Security for django-tradukoj 1.2.4

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page