多语言DB设计,具有类似的可翻译字段

时间:2018-05-02 11:06:06

标签: mysql database database-design localization internationalization

我没有为我正在处理的新项目设计数据库架构。

因此,挑战如下:

  • 有一个表Items
  • 每个Item都有可翻译的 description_60description_180文字,(后缀编号代表存储的描述类型,例如60表示60 char long)以及与apiSourceName
  • 等每个相关联的字段

我看到有两个选项:

1

descriptions_translations

  Id
description_60
description_180
description_300
apiSourceName_60
apiSourceName_180
....
...

看起来不太好,因为我们可能会得到很多NULL字段 和

2

descriptions_60_translations
  Id
description_60
apiSourceName
languageId
...
...

3其他?

我完全接受其他建议!

另外,另一个挑战是我想在Item表格中存储description_60文本。这可能没有重复数据吗?

更新 根据答案倾向于更多:

descriptions_translations
=========================
  id
itemId
description_type =>60, 120, 180 etc
`description` => 'This video is ...'
apiSourceName => youtube, dailymotion etc
languageId => en, es etc
...
...

对于60个字符和1000个字符长的文本使用相同列类型的任何缺点?

3 个答案:

答案 0 :(得分:2)

这是一种很好的方法,可以避免向用户显示垃圾:

在Items表中放置一个实际的描述字段。例如,美国(我们在权重和衡量方面落后于它)可能是:

Bread, brown, 1 pound loaf

然后构建一个包含三列的翻译表:langoriginal,翻译`。

例如:

lang   original                     translated
 es    Bread, brown, 1 pound loaf   Hogaza de pan integral, 450g
 fr    Bread, brown, 1 pound loaf   Miche de pain brun, 450g
 de    Bread, brown, 1 pound loaf   Laib Schwarzbrot, 450g

然后执行这样的查询来获取翻译:

SELECT COALESCE(t.translated, i.name) as name
  FROM Items
  LEFT JOIN Translation t ON t.lang = 'se' AND i.name = t.translated

这样,您的瑞典客户将获得原始项目名称(直到您提供瑞典语翻译),您的墨西哥客户将获得适当的翻译。诀窍是COALESCE ... LEFT JOIN查询模式。

您可能希望匹配名称ID值的翻译而不是名称本身。但是,对于它的价值,像WordPress这样的常见系统中的本地化与我建议的名称文本相匹配。

修改关于使用文字匹配而不是ID的效率。

假设您的翻译表中有1000万件商品。平均而言,每个项目200个字节。对于索引,我们说每个项目有400个字节。这个表的4千兆字节。在高质量的云计算机上,这将花费每月0.11到0.14美元。使用ID将略低于一半。说1.5千兆字节。所以差价大约是每月0.06美元。此外,云计算机的存储容量最小。

查找:如果正确索引表,文本匹配不会比id匹配慢得多。并且,当人们查找信息时,它不是大量发生的。

答案 1 :(得分:1)

您需要Languages table,例如

  

语言(身份证,姓名)

此外,您需要ItemDescriptions table,例如

  

ItemDescriptions(id,itemId,languageID,content)

您将insert values加入Languages table,例如

60, 'English' 
180, 'Hungarian'

记录到Items表中,如

1, 'Toothpaste'

并记录到ItemDescriptions表中,如

1, 1, 60, 'Best Toothpaste'
2, 1, 180, 'Legjobb Fogkrém'

因此,每个项目的Items table都会有一条记录,每种语言的Languages table都有一条记录,而且ItemDescriptions table他们翻译了Languages个。{/ p>

修改

事实证明,每种语言都有多种语言和多种描述。因此,我们需要将ItemDescriptions的定义更改为

  

ItemDescriptions(id,itemId,languageID,content60,content180,   content300)

所以每条记录都会包含所有相应的描述。

EDIT2

由于您描述了每个描述都需要额外的数据,因此很明显,给定的描述将不再是属性,而是记录。这意味着我们有两种可能的解决方案(对于这两种解决方案,我都避免因缺少信息而定义其他数据,但您可以定义各自的列):

第一个解决方案

  

ItemDescriptions(id,itemId,languageID,content,maxLength)

其中maxLength可分别为60,180,300。您的其他值将是ItemDescriptions table内的列。如果您对varchar(300)使用content,那么您将不会使用不必要的字节将值存储在content中。

第二种解决方案

  

ItemDescriptions80(id,itemId,languageID,content)

     

ItemDescriptions180(id,itemId,languageID,content)

     

ItemDescriptions300(id,itemId,languageID,content)

这些单独的表将存储单独的值,在这种情况下,您需要在每个表中使用单独的列以及其他数据。

比较

如果您使用varchar作为content的类型,那么就处理的简单性而言,第一种方法似乎优于第二种方法,无论何时insertupdate值,您需要确保maxLength有效(分别等于60,180或300)且content不超过maxLength 。您可以通过自己的应用程序,或通过记录级trigger on insert or update执行此操作。

答案 2 :(得分:0)

决定列的最大尺寸,然后选择

  • 对于“短”固定长度字符串(zipcode,country_code,UUID等),请使用CHAR(..) CHARACTER SET ascii

  • 对于总是为“短”的“短”字符串,请使用VARCHAR(...),其限制永远不会超过。你选择的限制无关紧要 - 60对80是无关紧要的。

  • 对于中等大小的字符串,请考虑VARCHAR(255)。 (如果您使用的是5.5或5.6和utf8mb4,请使用191。)

  • 对于较长的字符串,请使用TEXT(64K限制)或MEDIUMTEXT(16M限制)。

这些选择涉及实施细节,对大多数用户来说没有区别。

几乎没有人需要“以60个字符砍掉我的字符串”的功能。如果确实需要,那么应用程序可能需要做的比数据库模式更多。