Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Per-record default language #88

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

bbliem
Copy link

@bbliem bbliem commented Aug 24, 2022

So far, modeltrans assumed that the value of an original field (a translatable field when used without a language suffix; for example title, but not title_nl) is in the Django default language, which is the one specified by the setting LANGUAGE_CODE. Translations to any other language will be stored in the model's implicitly generated JSON field.

In some cases, it may be desired to use per-record default languages instead of a single global default language. For example, for a model for organizations from different parts of the world, each instance has a name that is in the respective local language and it may be desired to use this local-language name by default instead of storing it in the JSON field and leaving the original field empty for potentially many instances.

This PR adds an argument default_language_field to TranslationField that allows users to refer to a field that specifies the language of the original field. The default language field can be either in the same instance or in another reachable via foreign keys using the __ syntax.

Example:

class Organization(models.Model):
    name = models.CharField(max_length=255)
    language = models.CharField(max_length=2)
    i18n = TranslationField(fields=("name",), default_language_field="language")

class Department(models.Model):
    name = models.CharField(max_length=255)
    organization = models.ForeignKey(Organization, on_delete=models.CASCADE)
    i18n = TranslationField(fields=("name",), default_language_field="organization__language")

Now, no matter the LANGUAGE_CODE setting, for both of the following instances the name field will contain the local
name and the JSON field i18n will be empty:

amsterdam = Organization.objects.create(name="Gemeente Amsterdam", language="nl")
helsinki = Organization.objects.create(name="Helsingin kaupunki", language="fi")

In addition, the names are also available in amsterdam.name_nl and helsinki.name_fi.

Please see the documentation for this feature (docs/pages/working-with-models.rst) for some caveats.

In particular, changing the default language is not supported at the moment because it's nontrivial when __ is used in default_language_field, but if there is interest in that I could try writing some code for that as well.

I also found what could be considered a bug in modeltrans (issue #84). So far, the current PR fixes it when default_language_field is used, but it doesn't change the behavior when default_language_field is not used in order to keep the behavior the same for existing applications. Perhaps it would be a good idea to make this the default behavior, however.

I'm happy to receive feedback and make some changes if needed.

@bbliem bbliem changed the title Feature/per record default language Per-record default language Aug 24, 2022
bbliem added 2 commits August 24, 2022 13:06
The original field might not be in the fallback chain. `__get__()` falls
back to the original field if all else fails, so it may be surprising
that `instance.field_i18n` falls back to the original field but
`Model.objects.values_list('field_i18n')` does not.

Note that this change might break existing applications.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant