How to define an entity with translations using DDD

2k Views Asked by At

I have a small application using Domain Driven Design and now I would like to have an entity with translations.

I have read on the internet that the best practices in Domain Driven Design is to separate the translations from the model but I don't know how to do it.

Here an example of what I have:

@Entity
class Product {
    @Id
    private String id;
    private String name;
    private String description;
    private BigDecimal price;
    private BigDecimal originalPrice;

    ...
}

@Service
class ProductService {

    @Autowired
    private ProductRepository productRepository;

    public List<Product> getAll() {
        return productRepository.findAll();
    }

    public List<Product> getById(String id) {
        return productRepository.findById(id);
    }

    public List<Product> create(ProductDto productDto) {
        Product product = new Product(
            productDto.getName(),
            productDto.getDescription(),
            productDto.getPrice(),
            productDto.getOriginalPrice()
        );
        return productRepository.save(product);
    }
}

Then my questions are:

Imagine I am receiving the translations in the product DTO and I would like to know how to do it.

Thanks and appreciate your help.

2

There are 2 best solutions below

2
On

I would recommend to differ your domain model from your data model. While in your domain model you really will not care about any translations and it will look like as what you've proposed, your data model may look different:

@Entity
class Product {
    @Id
    private String id;
    private BigDecimal price;
    private BigDecimal originalPrice;
    private List<ProductTranslation> translations;

    ...
}

@Entity
class ProductTranslation{
    @Id
    private String id;
    private String name;
    private String description;
    private Int languageId;

    ...
}

Then inside of your repository youl will map from your domain model to your data model, while you will take languageId from some application settings.

1
On

This isn't something your core domain would really be interested in and you should need to model it. You are probably going to have some translation sub-domain where you would be interested in these things but that design would be focused on mapping a key/language pair to a translation.

Your core domain would be using some default language for your location and that would be the well known and required entry in the core domain. For example, your Product may have a ProductID (or SKU or the like) as well as a Description. That description will be in the default language.

Your translation would be on the integration layer as more of an infrastructure service and would provide the translated description if there is one available; else the default one which should be required in your domain.

update:

another answer I gave: DDD: DTO usage with different logic

For example (broadly):

public Translation 
{
    string Locale { get; set; }
    string Value { get; set; }
}

public interface ILocalisationQuery
{
    Translation For(string locale, string key);
    IEnumerable<Translation> For(string key);
}

public class LocalisationQuery : ILocalisationQuery
{
    public Translation For(string locale, string key)
    {
        // lookup from localisation data store
    }

    public IEnumerable<Translation> For(string key)
    {
        // lookup from localisation data store
    }
}

You'd implement a strategy that makes sense to you and is applicable to your use case. Say you want to get the Fench description for the spoon product and you have used product-spoon as the convention for the key: localisation.For('fr', 'product-spoon');.

For my JavaScript front-ends I use i18next.