Multi language database, with default fallback

后端 未结 2 702
春和景丽
春和景丽 2021-01-29 19:47

I have a question that, I know, has been widely discussed about, but in my opinion, there is one aspect that still needs clarification.

I am creating a web-application w

2条回答
  •  醉梦人生
    2021-01-29 20:27

    Some notes upfront:

    • my answer is more of an addition to my answer to this question, where you added a comment which then led to this question
    • in my answer I'm using C# and MS SQL Server (and I'll leave out any OR-mapping specific code)

    In my applications, I use two different approaches for loading multilingual data, depending on the use case:

    Administration / CRUD

    In the case where the user is entering data or editing existing data (e.g. a product with its translations) I'm using the same approach as you have shown above in your question, e.g:

    public class Product
    {
        public int ID {get; set;}
        public string SKU {get; set;}
        public IList Translations {get; set;}
    }
    public class ProductTranslation
    {
        public string Language {get; set;}
        public bool IsDefaultLanguage {get; set;}
        public string Title {get; set;}
        public string Description {get; set;}
    }
    

    I.e. I'll let the OR-mapper load the product instance(s) with all their translations attached. I then iterate through the translations and pick the ones needed.

    Front-end / read-only

    In this case, which is mainly front-end code, where I usually just display information to the user (preferably in the user's language), I'm using a different approach:

    First of all, I'm using a different data model which doesn't support/know the notion of multiple translations. Instead it is just the representation of a product in the "best" language for the current user:

    public class Product
    {
        public int ID {get; set;}
        public string SKU {get; set;}
    
        // language-specific properties
        public string Title {get; set;}
        public string Description {get; set;}
    }
    

    To load this data, I'm using different queries (or stored procedures). E.g. to load a product with ID @Id in the language @Language, I'd use the following query:

    SELECT
        p.ID,
        p.SKU,
        -- get title, description from the requested translation,
        -- or fall back to the default if not found:
        ISNULL(tr.Title, def.Title) Title,
        ISNULL(tr.Description, def.Description) Description
      FROM Products p
      -- join requested translation, if available:
      LEFT OUTER JOIN ProductTranslations tr
        ON p.ID = tr.ProductId AND tr.Language = @Language
      -- join default language of the product:
      LEFT OUTER JOIN ProductTranslations def
        ON p.ID = def.ProductId AND def.IsDefaultLanguage = 1
      WHERE p.ID = @Id
    

    This returns the product's title and description in the requested language if a translation for that language exists. If no translation exists, the title and description from the default language will be returned.

提交回复
热议问题