What is the best way to implement multilingual domain objects using NHibernate?

What is the best way to create domain objects that can have multilingual fields. An example would be the Product class with a description that is multilingual.

I found some links, but could not decide which one is the best.

Anyone with experience using NHibernate with multilingual data. Is there a better way?

+4
source share
4 answers

The third option looks great. The hibernation mapping is displayed, but not the database schema β€” if this is not enough, then I will draw it here:

dictionary ---------- ID: int - identity name: nvarchar(255) phrase ------ dictionary_id:int (fkey dictionary.ID) culture_id:int (LCID) phrase:nvarchar(255) - this is the default size - seems too small 

According to this blog entry 255 is the default string length for String values. To overcome the short string length in the text of a phrase, you can change the <element> to

 <element column="phrase" type="String" length="4001"></element> 

To use this in your domain model, you add the PhraseDictionary property to your entity where you want to translate the text. For instance. title property or decription property.

I think the article describes a great approach, and exactly the one that I would go for.

EDIT: In response to the comments, make the length less than 4001 if you know that the maximum maximum size is less than this, as this will usually be faster. In addition, NHibernate will lazily retrieve a collection, but it can receive all items at once. You can customize the profile to determine if it has performance implications. (If you have only a few languages, then I doubt that you will see the difference.) If you have many languages ​​(say 50+), it may be useful to create custom properties to get localized text. They will issue requests for specially needed text. More importantly, you can get all the text for a given object in one request, and not each property of the localized text as a separate request.

Please note that this extra effort is only necessary if profiling gives you reason to worry about performance. Most likely, the implementation in the article as it will will function more than adequately.

+2
source

I only have experience for Hibernate, but since nHibernate is so similar:

One option is to determine the type of the MultilingualString component with members for each language (this assumes that many languages ​​are known at the time of encoding). This type is also a convenient place to place the recipient for a string by language identifier.

 class MultiLingualString { String english; String chinese; String klingon; String forLanguage(Language lang) { switch (lang) { // you can guess what goes here } } } 

This leads to the fact that the rows for all languages ​​are stored in separate columns in the database, and the representation in the world of objects preserves accurate detail.

The advantage is that combining is not required to extract the rows. On the other hand, the only way not to take a line with this approach is to use projection, which is a serious limitation if the lines are large, numerous, and rarely needed.

If you do this a lot, writing a UserType might be worth it.

+1
source

From a strictly oriented database point of view with SQL Server, you should have one table with all the underlying data (record key, dates, numbers, etc.) and one table with all the translated string data. Let me call the two tables Base and Base_Description.

The database guarantees that for each record there is one key, the key can be a string or an automatically generated identifier, depending on your specific use case.

The Base_Description table refers to the base table, but also contains a value for choosing the language in which the data is located. In my projects, we use the langid column from sys.languages, because we can set the connection language to, and then capture it with @@ LANGID for most operations.

In our testing, we found that it is much faster than having multiple fields for each language, and also makes it easier to add other languages. We also use SQL Server full-text indexing, and it fully works with this method. You must index in a neutral language, and then you can select the language to search at runtime (also filtering it by the LangID column in Base_Description).

+1
source

Do your requirements include domain objects that actually have multilingual properties in the same object? And if so, then these are unlimited translations stored in the object (in the collection, say - in this case, I would say that it should be exactly the same as any master / part or parent / child collection) or fixed translations in which Should languages ​​(and therefore displaying the results of a stored proc or something else) have to be set statically?

In many internationalized applications that I worked on, the data was in only one language - customer names, product names (there was no point in comparing even identical products used in one country for products in another, they all had different distributors and different SKUs and , of course, localized prices). The interface was also only in one language (at a time). Thus, all domain objects require only one language at a time. Thus, the language of translation will be determined when creating an instance of the object.

We had user interfaces for translation, which allowed users to update translated texts, but this required only two languages ​​at a time (local and default). I see that this is closest to what you are talking about. I assume that you will have child collections for each translatable property with all possible translations in the collection. This will probably be closest to the second solution in the third article that you linked. Of course, at this point you will also need to see if you want to eagerly / lazy download, etc.

+1
source

Source: https://habr.com/ru/post/1310224/


All Articles