Guide: Context

This module provides an in depth knowledge of the Translations context.

Important

The examples are assumed to CRUD this dataset.

Type\Lang

English

German

Continent

Europe

Europa

Asia

Asien

Country

Germany

Deutschland

South Korea

Südkorea

City

Cologne

Köln

Seoul

Seul

Please memorize this dataset in order to understand the examples better.

What is context

When something is going to be stated it can be done so in the context of a certain language.

Initialize a context

To initialize a context use the Context class. The instances to be affected by the context must be defined in the initialization, meaning which entity and what relations of it should the context act upon. This is called the context’s purview.

All the actions like reading the translations, updating the translations, etc only affects the objects in the defined purview.

To initialize a context for an instance and some relations of it:

from translations.context import Context
from sample.models import Continent

europe = Continent.objects.get(code='EU')
relations = ('countries', 'countries__cities',)

# initialize context
with Context(europe, *relations) as context:
    print('Context initialized!')
Context initialized!

To initialize a context for a queryset and some relations of it:

from translations.context import Context
from sample.models import Continent

continents = Continent.objects.all()
relations = ('countries', 'countries__cities',)

# initialize context
with Context(continents, *relations) as context:
    print('Context initialized!')
Context initialized!

To initialize a context for a list of instances and some relations of it:

from translations.context import Context
from sample.models import Continent

continents = list(Continent.objects.all())
relations = ('countries', 'countries__cities',)

# initialize context
with Context(continents, *relations) as context:
    print('Context initialized!')
Context initialized!

The entity must be a model instance, a queryset or a list of model instances. The model of the entity must be translatable.

Each relation may be divided into separate parts by __s to represent a deeply nested relation. Each part must be a related_name. The models of the relations must be translatable.

Note

It is recommended for the relations of the entity to be prefetched before initializing a context, in order to reach optimal performance.

To do this use select_related, prefetch_related or prefetch_related_objects.

Creating the translations

To create the translations of the context’s purview in a language use the create() method. This creates the translations using the translatable fields of the context’s purview. It accepts a language code which determines the language to create the translation in.

To create the translations of an instance and some relations of it:

from translations.context import Context
from sample.models import Continent

europe = Continent.objects.get(code='EU')
relations = ('countries', 'countries__cities',)

with Context(europe, *relations) as context:

    # change the instance like before
    europe.name = 'Europa'
    europe.countries.all()[0].name = 'Deutschland'
    europe.countries.all()[0].cities.all()[0].name = 'Köln'

    # create the translations in German
    context.create('de')

    print('Translations created!')
Translations created!

To create the translations of a queryset and some relations of it:

from translations.context import Context
from sample.models import Continent

continents = Continent.objects.all()
relations = ('countries', 'countries__cities',)

with Context(continents, *relations) as context:

    # change the queryset like before
    continents[0].name = 'Europa'
    continents[0].countries.all()[0].name = 'Deutschland'
    continents[0].countries.all()[0].cities.all()[0].name = 'Köln'

    # create the translations in German
    context.create('de')

    print('Translations created!')
Translations created!

To create the translations of a list of instances and some relations of it:

from translations.context import Context
from sample.models import Continent

continents = list(Continent.objects.all())
relations = ('countries', 'countries__cities',)

with Context(continents, *relations) as context:

    # change the list of instances like before
    continents[0].name = 'Europa'
    continents[0].countries.all()[0].name = 'Deutschland'
    continents[0].countries.all()[0].cities.all()[0].name = 'Köln'

    # create the translations in German
    context.create('de')

    print('Translations created!')
Translations created!

The language code must already be declared in the LANGUAGES setting. It is optional and if it is not passed in, it is automatically set to the active language code.

Creating duplicate translations for a field raises IntegrityError, to update the translations check out updating the translations.

Note

Creating only affects the translatable fields that have changed.

If the value of a field is not changed, the translation for it is not created. (No need to set all the translatable fields beforehand)

Reading the translations

To read the translations of the context’s purview in a language use the read() method. This reads the translations onto the translatable fields of the context’s purview. It accepts a language code which determines the language to read the translation in.

To read the translations of an instance and some relations of it:

from translations.context import Context
from sample.models import Continent

europe = Continent.objects.get(code='EU')
relations = ('countries', 'countries__cities',)

with Context(europe, *relations) as context:

    # read the translations in German
    context.read('de')

    # use the instance like before
    print(europe)
    print(europe.countries.all())
    print(europe.countries.all()[0].cities.all())
Europa
<TranslatableQuerySet [
    <Country: Deutschland>,
]>
<TranslatableQuerySet [
    <City: Köln>,
]>

To read the translations of a queryset and some relations of it:

from translations.context import Context
from sample.models import Continent

continents = Continent.objects.all()
relations = ('countries', 'countries__cities',)

with Context(continents, *relations) as context:

    # read the translations in German
    context.read('de')

    # use the queryset like before
    print(continents)
    print(continents[0].countries.all())
    print(continents[0].countries.all()[0].cities.all())
<TranslatableQuerySet [
    <Continent: Asien>,
    <Continent: Europa>,
]>
<TranslatableQuerySet [
    <Country: Deutschland>,
]>
<TranslatableQuerySet [
    <City: Köln>,
]>

To read the translations of a list of instances and some relations of it:

from translations.context import Context
from sample.models import Continent

continents = list(Continent.objects.all())
relations = ('countries', 'countries__cities',)

with Context(continents, *relations) as context:

    # read the translations in German
    context.read('de')

    # use the list of instances like before
    print(continents)
    print(continents[0].countries.all())
    print(continents[0].countries.all()[0].cities.all())
[
    <Continent: Europa>,
    <Continent: Asien>,
]
<TranslatableQuerySet [
    <Country: Deutschland>,
]>
<TranslatableQuerySet [
    <City: Köln>,
]>

The language code must already be declared in the LANGUAGES setting. It is optional and if it is not passed in, it is automatically set to the active language code.

Note

Reading only affects the translatable fields that have a translation.

If there is no translation for a field, the value of the field is not changed. (It remains what it was before)

Warning

Any methods on the relations queryset which imply a database query will reset previously translated results:

from translations.context import Context
from sample.models import Continent

continents = Continent.objects.prefetch_related(
    'countries',
)

with Context(continents, 'countries') as context:
    context.read('de')
    # querying after translation
    print(continents[0].countries.exclude(name=''))
<TranslatableQuerySet [
    <Country: Germany>,
]>

In some cases the querying can be done before the translation:

from django.db.models import Prefetch
from translations.context import Context
from sample.models import Continent, Country

# querying before translation
continents = Continent.objects.prefetch_related(
    Prefetch(
        'countries',
        queryset=Country.objects.exclude(name=''),
    ),
)

with Context(continents, 'countries') as context:
    context.read('de')
    print(continents[0].countries.all())
<TranslatableQuerySet [
    <Country: Deutschland>,
]>

Updating the translations

To update the translations of the context’s purview in a language use the update() method. This updates the translations using the translatable fields of the context’s purview. It accepts a language code which determines the language to update the translation in.

To update the translations of an instance and some relations of it:

from translations.context import Context
from sample.models import Continent

europe = Continent.objects.get(code='EU')
relations = ('countries', 'countries__cities',)

with Context(europe, *relations) as context:

    # change the instance like before
    europe.name = 'Europa (changed)'
    europe.countries.all()[0].name = 'Deutschland (changed)'
    europe.countries.all()[0].cities.all()[0].name = 'Köln (changed)'

    # update the translations in German
    context.update('de')

    print('Translations updated!')
Translations updated!

To update the translations of a queryset and some relations of it:

from translations.context import Context
from sample.models import Continent

continents = Continent.objects.all()
relations = ('countries', 'countries__cities',)

with Context(continents, *relations) as context:

    # change the queryset like before
    continents[0].name = 'Europa (changed)'
    continents[0].countries.all()[0].name = 'Deutschland (changed)'
    continents[0].countries.all()[0].cities.all()[0].name = 'Köln (changed)'

    # update the translations in German
    context.update('de')

    print('Translations updated!')
Translations updated!

To update the translations of a list of instances and some relations of it:

from translations.context import Context
from sample.models import Continent

continents = list(Continent.objects.all())
relations = ('countries', 'countries__cities',)

with Context(continents, *relations) as context:

    # change the list of instances like before
    continents[0].name = 'Europa (changed)'
    continents[0].countries.all()[0].name = 'Deutschland (changed)'
    continents[0].countries.all()[0].cities.all()[0].name = 'Köln (changed)'

    # update the translations in German
    context.update('de')

    print('Translations updated!')
Translations updated!

The language code must already be declared in the LANGUAGES setting. It is optional and if it is not passed in, it is automatically set to the active language code.

Note

Updating only affects the translatable fields that have changed.

If the value of a field is not changed, the translation for it is not updated. (No need to initialize all the translatable fields beforehand)

Deleting the translations

To delete the translations of the context’s purview in a language use the delete() method. This deletes the translations for the translatable fields of the context’s purview. It accepts a language code which determines the language to delete the translation in.

To delete the translations of an instance and some relations of it:

from translations.context import Context
from sample.models import Continent

europe = Continent.objects.get(code='EU')
relations = ('countries', 'countries__cities',)

with Context(europe, *relations) as context:

    # delete the translations in German
    context.delete('de')

    print('Translations deleted!')
Translations deleted!

To delete the translations of a queryset and some relations of it:

from translations.context import Context
from sample.models import Continent

continents = Continent.objects.all()
relations = ('countries', 'countries__cities',)

with Context(continents, *relations) as context:

    # delete the translations in German
    context.delete('de')

    print('Translations deleted!')
Translations deleted!

To delete the translations of a list of instances and some relations of it:

from translations.context import Context
from sample.models import Continent

continents = list(Continent.objects.all())
relations = ('countries', 'countries__cities',)

with Context(continents, *relations) as context:

    # delete the translations in German
    context.delete('de')

    print('Translations deleted!')
Translations deleted!

The language code must already be declared in the LANGUAGES setting. It is optional and if it is not passed in, it is automatically set to the active language code.

Resetting the translations

To reset the translations of the context’s purview to the default language use the reset() method. This resets the translations on the translatable fields of the context’s purview.

To reset the translations of an instance and some relations of it:

from translations.context import Context
from sample.models import Continent

europe = Continent.objects.get(code='EU')
relations = ('countries', 'countries__cities',)

with Context(europe, *relations) as context:

    # changes happened to the fields, create, read, update, delete, etc...
    context.read('de')

    # reset the translations
    context.reset()

    # use the instance like before
    print(europe)
    print(europe.countries.all())
    print(europe.countries.all()[0].cities.all())
Europe
<TranslatableQuerySet [
    <Country: Germany>,
]>
<TranslatableQuerySet [
    <City: Cologne>,
]>

To reset the translations of a queryset and some relations of it:

from translations.context import Context
from sample.models import Continent

continents = Continent.objects.all()
relations = ('countries', 'countries__cities',)

with Context(continents, *relations) as context:

    # changes happened to the fields, create, read, update, delete, etc...
    context.read('de')

    # reset the translations
    context.reset()

    # use the queryset like before
    print(continents)
    print(continents[0].countries.all())
    print(continents[0].countries.all()[0].cities.all())
<TranslatableQuerySet [
    <Continent: Asia>,
    <Continent: Europe>,
]>
<TranslatableQuerySet [
    <Country: Germany>,
]>
<TranslatableQuerySet [
    <City: Cologne>,
]>

To reset the translations of a list of instances and some relations of it:

from translations.context import Context
from sample.models import Continent

continents = list(Continent.objects.all())
relations = ('countries', 'countries__cities',)

with Context(continents, *relations) as context:

    # changes happened to the fields, create, read, update, delete, etc...
    context.read('de')

    # reset the translations
    context.reset()

    # use the list of instances like before
    print(continents)
    print(continents[0].countries.all())
    print(continents[0].countries.all()[0].cities.all())
[
    <Continent: Europe>,
    <Continent: Asia>,
]
<TranslatableQuerySet [
    <Country: Germany>,
]>
<TranslatableQuerySet [
    <City: Cologne>,
]>