Concepts
This section will explain several concepts in closer detail for when the reference might not be sufficient.
Registering models
SQLModel-translation can translate fields of SQLModel classes without modifying the original class.
Consider the following example which translates Book into english and polish.
from modeltranslation import Translator, TranslationOptions
from sqlmodel import SQLModel
class Book(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
title: str
translator = Translator(
default_language="en",
languages=("en", "pl"),
)
@translator.register(Book)
class BookTranslationOptions(TranslationOptions):
fields = ("title",)
required_languages = ("en",)
Book now looks like this.
class Book(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
title: str | None
title_pl: str | None
title_en: str
Let's see a more complicated example and explain it step by step.
from modeltranslation import Translator, TranslationOptions
from sqlmodel import SQLModel
class Book(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
title: str
author: str
translator = Translator(
default_language="en",
languages=("en", "pl", "fr", "es"),
fallback_languages={"fr": ("pl", "en"), "default": ("fr",)},
)
@translator.register(Book)
class BookTranslationOptions(TranslationOptions):
fields = ("title",)
required_languages = {"fr": ("title", "author"), "default": ("title",)}
fallback_values = {"title": ("Title"), "author": ("No translation provided")}
-
fallback_languages={"fr": ("es", "pl"), "default": ("en",)}This means that when there is no value for french, spanish and polish will be tried next. For other languagesenwill be used as the first fallback. -
required_languages = {"fr": ("title", "author"), "default": ("title",)}Title is required in all languages. Additionally the author is required to be translated in french. -
fallback_values = {"title": ("Title"), "author": ("No translation provided")When language fallbacks fail then fallback values will be used instead.
Exceptions
Sometimes the translation configuration can be inconsistent. For example:
from modeltranslation import Translator, TranslationOptions
translator = Translator(
default_language="en",
languages=("en", "pl"),
)
class BookTranslationOptions(TranslationOptions):
fields = ("title",)
required_languages = ("fr")
fr is not declared in the translator.
ImproperlyConfiguredError will be thrown whenever inconsistencies like this are detected.
For more details about possible configuraion options see Translator and TranslationOptions. If this is not sufficient, try looking up the tests.
Each test for a configuration option is an example exactly like this and is fairly readable to new users.
Accessing translated fields
Rule 1 - Reading the value from the original field returns the value translated to the current language.
Rule 2 - Assigning a value to the original field updates the value in the associated current language translation field.
Rule 3 - If both fields - the original and the current language translation field - are updated at the same time, the current language translation field wins.
The original field is inaccessible and should be considered invalid.
Using SQLModel queries
Registering translations makes all SQLModel queries work with the new translation fields.
For example:
update(Book).where(Book.author == "J.R.R. Tolkien").values(title="translation")
select(Book).where(Book.title_en == "english_title")
There is one exception which might feel unnatural.
Selecting columns only reroutes to the correct column based on the active langugage.
This means that any fallback languages or values configured both in Translator, TranslationOptions and will not apply here.