适当的多语言模式,还是矫kill过正?


8

更新2:我实际上已经使用了它,经过几次调整后,它很棒。这是我关于其实际设计并在实践中的文章:http : //tim.hithlonde.com/2013/lemon-schema-works/

我正在构建一个Web应用程序,并且希望它支持多种语言。此结构包含两个组件:

  1. 用词条连接语言环境(“英语”,“荷兰语”等),并用Rosetta Stone连接词条和特定语言的词条。
  2. 按页面对术语进行分组。我不想通过页面上可能需要的30多个术语来选择SELECT term1,term2等。我想问一下他们所连接的页面。

这是我建议的表结构(请注意,所有ID之间都具有关系/索引以进行非常有效的查询):

架构图

  * locale
      * id
      * value //English, Deutch, etc//
  * terms
    * id
    * value //In English//
  * page 
    * id
    * value //Think add entry, menu//
  * page_group //group all terms to a page, for easy pulling//
    * id
    * page.id
    * term.id
  * rosetta
    * id
    * locale.id
    * term.id
    * value //french word for amount, description, etc//

这将允许以下查询:

SELECT localization.value,
        terms.value
FROM localization
INNER JOIN terms ON terms.id=localization.termid
INNER JOIN page_group ON page_group.termid=localization.termid
INNER JOIN page ON page.id=page_group.pageid
INNER JOIN locale ON locale.id=localization.localeid
WHERE page.value='add_entry' AND locale.id=custlangid
ORDER BY terms.id

我只需要问两个项目。我需要的语言ID和我需要的页面。它会以指定的语言提供该页面术语组中的所有术语。

我认为这是一个非常好的结构,但我希望收到一些反馈。

更新:为澄清起见,我们只是在谈论UI组件的本地化。(标签,导航,有用的文本)用户输入的所有信息都将以unicode而不是此模式存储。

更新2:我实际上已经使用了它,这很棒。这是我关于实际设计并在实际操作中的文章:http : //tim.hithlonde.com/2013/lemon-schema-works/


1
通常,(从我所看到的)本地化是通过Web上的模板完成的。您希望从数据库方面进行本地化?
Philᵀᴹ

我想本地化所有标签,导航菜单和任何有用的文本(警告等)。我从db抓取此文件的原因是,我不需要模板中的逻辑。在我的模板中,我想<?php echo $term['term_in_english'];?>争取一种可靠的MVC方法。
蒂姆·哈伯萨克

Answers:


6

我们已经做了很多工作,并且(管理)用户可以实时修复翻译。(您仍然可能需要缓存层,但是我完全不愿意使用真正的数据库而不是资源文件来驱动它-它使您拥有大量查询和查找需要翻译的内容的能力,等等​​)。我认为您的架构可能很好,所以我只传递一些我们学到的东西,希望它有用。

您遗漏的一件事是带有插入点的短语。在下面的示例中,顺序颠倒了,语言仍然是英语,但这很容易是两种不同的语言-假设这只是两种通常以不同顺序排列事物的语言。

Hello, <username> you have <x> points!

You've got <x> points to spend, <username>!

在我们的.NET之前的版本中,我们有一个例程进行插入,因此短语看起来像这样:

Hello, {0:username} you have {1:points} points!

You've got {1:points} points to spend, {0:username}!

这显然只是在你的代码可以用作<%= String.Format(phrase, username, points); %>或类似

这对翻译有帮助。但是不幸的是,.NET String.FOrmat不支持在格式字符串中进行注释。

如您所说,您不希望在具有本地化意识或元短语的php中处理该问题。

所以我们有了一个主短语表:

短语,英语,补充信息

和一个本地化的表:

词组,语言环境,翻译

您还使用INNER JOINS假设存在本地化版本-我们倾向于将它们保留下来,直到将其翻译为止,这样您的查询最终将一开始不返回任何内容(甚至不是默认值)

如果翻译不存在,我们的翻译默认为英语,然后回退到代码提供的情况下(以防数据库没有ID,并且从代码中还可以清楚地看出是什么短语标识符“ TXT_LNG_WRNNG_INV_LOW” )-因此,此查询与我们使用的等效:

SELECT COALESCE(localized.translation, phrase.english, @fallback)
FROM DUAL
LEFT JOIN phrase
    ON phrase.phraseid = @phraseid
LEFT JOIN localized
    ON localized.phraseid = phrase.phraseid
    AND localized.localeid = @localeid

显然,使用页面系统可以一次获得所有内容。

我们倾向于不将内容链接到页面,因为它们在页面之间被大量重复使用(而不仅仅是在页面片段或控件中),但这当然可以。

对于Windows本地应用程序,我们使用了反射和从控件到翻译标记的映射文件,因此翻译不需要重新编译(在.NET以前的应用程序中,我们必须使用标记或其他特殊标记来标记控件。属性)。在PHP或ASP.NET MVC中,这可能会出现更多问题,但在具有完善的服务器端页面模型的ASP.NET中,这可能会出现问题。

对于测试,您显然可以很容易地查询以查找丢失的翻译。要查找需要标记的地方,请使用pig-latin或Klingon翻译整个短语词典,或使用?替换每个非空格字符。-英语应该突出,让您知道HTML中已经包含一些明文。


这次真是万分感谢!我没有考虑插入点。我不相信我的应用程序实际上会包含任何应用程序,但是请牢记这一点。另外,感谢您对架构的评论。我已经做了一段时间的数据库设计,但是由于没有足够的同行来比较笔记,这使我有时不确定自己朝着正确的方向前进。:)
蒂姆·哈伯萨克

0

通常,翻译是由外部专业公司完成的。这样,在数据库内管理翻译后的内容将很麻烦。他们最好通过平台提供的某种语言功能来管理“捆绑包”或属性文件。为此,您只需在数据库中放置一个助记符即可。然后,根据所需的语言,您将在捆绑软件中查找。例如。

Data:
Employee_Status = empl_status.active

language Bundles:
Employee.us:  
  empl_status.active=Active

Employee.es
  empl_status.active=<spanish translation goes here>

To get the localized content:
    String status = getLocalizedContent("Employee","empl_status.active", "us");
    String status = getLocalizedContent("Employee","empl_status.active", "es");
    String status = getLocalizedContent("Employee","empl_status.active");

我很困惑,因为我们在谈论同一件事。我将建造与您相当的产品getLocalizedContent。除了在控制器级别,我将请求连接到页面的所有术语以及所需的语言。该函数将调用我上面描述的查询,并发挥一些作用,因此我得到了一个关联数组,其中的键将是助记符,值将是术语。UI术语的数量很少(<100个),因此我认为在数据库中管理它不会有问题。我可能会构建一个简单的界面来输入翻译后的术语并捆绑页面。
Tim Habersack

0

只需创建3个表

1.)语言大师(LangId,LangName)

2.)资源管理器(ResourceMasterId,TableId,ColumnId,ColumnName)

3.)资源详细信息(ResourceMasterId,LangId,Value)

资源详细信息上的复合键(ResourceMasterId,LangId)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.