字符串和标签本地化和全球化的最佳实践 [关闭]
Posted
技术标签:
【中文标题】字符串和标签本地化和全球化的最佳实践 [关闭]【英文标题】:Best practice for localization and globalization of strings and labels [closed] 【发布时间】:2012-12-30 19:06:15 【问题描述】:我是一个拥有 20 多名开发人员的团队的一员。每个开发人员都在一个单独的模块上工作(大约 10 个模块)。在每个模块中,我们可能至少有 50 个 CRUD 表单,这意味着我们目前有近 500 个添加按钮、保存按钮、编辑按钮,等等
但是,因为我们想要全球化我们的应用程序,我们需要能够在我们的应用程序中翻译文本。例如,对于法语用户,add 这个词在任何地方都应该变成 ajouter。
到目前为止,我们所做的是,对于 UI 或表示层中的每个视图,我们都有一个翻译键/值对的字典。然后在渲染视图时,我们使用这个字典翻译所需的文本和字符串。但是,通过这种方法,我们在 500 个字典中得到了接近 500 个add。这意味着我们违反了 DRY 原则。
另一方面,如果我们把常用的字符串集中起来,比如把add放在一个地方,让开发者到处使用,就会遇到不确定字符串是否已经定义的问题是否在集中式字典中。
另一种选择可能是没有翻译词典,而使用谷歌翻译、必应翻译等在线翻译服务。
我们遇到的另一个问题是一些开发人员在按时交付项目的压力下记不住翻译键。例如,对于添加按钮的文本,一个开发者使用了add,而另一个开发者使用了new等
对应用程序的字符串资源进行全球化和本地化的最佳实践或最著名的方法是什么?
【问题讨论】:
JS EU 会议上Alex Sexton 的talk 主题Client Side Internationalization 是一个良好的开端。 【参考方案1】:jQuery.i18n 是一个轻量级的 jQuery 插件,用于在您的网页中实现国际化。它允许您将自定义资源字符串打包在“.properties”文件中,就像在 Java 资源包中一样。它根据提供的语言或浏览器报告的语言加载和解析资源包(.properties)。
要了解更多信息,请查看How to internationalize your pages using JQuery?
【讨论】:
链接不见了【参考方案2】:据我所知,有一个名为 localeplanet
的优秀库用于 javascript 中的本地化和国际化。此外,我认为它是原生的,并且不依赖于其他库(例如 jQuery)
图书馆网址:http://www.localeplanet.com/
另外看看Mozilla的这篇文章,可以找到非常好的客户端翻译方法和算法:http://blog.mozilla.org/webdev/2011/10/06/i18njs-internationalize-your-javascript-with-a-little-help-from-json-and-the-server/
所有这些文章/库的共同部分是它们使用i18n
类和get
方法(在某些方面还定义了一个较小的函数名称,如_
)来检索/转换key
到value
。在我的解释中,key
表示您要翻译的字符串,value
表示已翻译的字符串。
然后,您只需要一个 JSON 文档来存储 key
's 和 value
's。
例如:
var _ = document.webL10n.get;
alert(_('test'));
这里是 JSON:
test: "blah blah"
我相信使用当前流行的库解决方案是一种好方法。
【讨论】:
无意冒犯,但这不是 Afshin 已经尝试过的吗?他的问题是不同的开发人员很难记住要使用哪些键。我同意你描述的方法是要走的路。我不明白怎么可能。顺便说一句,感谢您提供的精彩链接。【参考方案3】:当您面临要解决的问题时(坦率地说,谁没有 这些天?),我们计算机人通常采取的基本策略 被称为“分而治之”。它是这样的:
将特定问题概念化为一组较小的子问题。 解决每个小问题。 将结果组合成特定问题的解决方案。但“分而治之”并不是唯一可能的策略。我们还可以采取更通用的方法:
将特定问题概念化为更一般问题的特例。 以某种方式解决一般问题。 使一般问题的解决方案适应具体问题。- 埃里克·利珀特
我相信在 ASP.Net/C# 等服务器端语言中已经存在许多解决此问题的方法。
我已经概述了问题的一些主要方面
问题:我们只需要加载所需语言的数据
解决方案:为此,我们将数据保存到每种语言的单独文件中
例如。 res.de.js, res.fr.js, res.en.js, res.js(默认语言)
问题:每个页面的资源文件应该分开,所以我们只得到我们需要的数据
解决方案:我们可以使用一些已经存在的工具,例如 https://github.com/rgrove/lazyload
问题:我们需要一个键/值对结构来保存我们的数据
解决方案:我建议使用 javascript 对象而不是字符串/字符串空气。 我们可以从 IDE 的智能感知中受益
问题:一般成员应存储在公共文件中,所有页面都应访问它们
解决方案:为此,我在 Web 应用程序的根目录中创建了一个名为 Global_Resources 的文件夹,并为我们命名为“Local_Resources”的每个子文件夹存储了一个全局文件
问题:每个子系统/子文件夹/模块成员都应覆盖其范围内的 Global_Resources 成员
解决方案:我考虑了每个文件
应用结构
root/ Global_Resources/ default.js default.fr.js UserManagementSystem/ Local_Resources/ default.js default.fr.js createUser.js Login.htm CreateUser.htm
文件对应的代码:
Global_Resources/default.js
var res =
Create : "Create",
Update : "Save Changes",
Delete : "Delete"
;
Global_Resources/default.fr.js
var res =
Create : "créer",
Update : "Enregistrer les modifications",
Delete : "effacer"
;
所需语言的资源文件应加载到从 Global_Resource 选择的页面上 - 这应该是所有页面上加载的第一个文件。
UserManagementSystem/Local_Resources/default.js
res.Name = "Name";
res.UserName = "UserName";
res.Password = "Password";
UserManagementSystem/Local_Resources/default.fr.js
res.Name = "nom";
res.UserName = "Nom d'utilisateur";
res.Password = "Mot de passe";
UserManagementSystem/Local_Resources/createUser.js
// Override res.Create on Global_Resources/default.js
res.Create = "Create User";
UserManagementSystem/Local_Resources/createUser.fr.js
// Override Global_Resources/default.fr.js
res.Create = "Créer un utilisateur";
manager.js 文件(此文件应最后加载)
res.lang = "fr";
var globalResourcePath = "Global_Resources";
var resourceFiles = [];
var currentFile = globalResourcePath + "\\default" + res.lang + ".js" ;
if(!IsFileExist(currentFile))
currentFile = globalResourcePath + "\\default.js" ;
if(!IsFileExist(currentFile)) throw new Exception("File Not Found");
resourceFiles.push(currentFile);
// Push parent folder on folder into folder
foreach(var folder in parent folder of current page)
currentFile = folder + "\\Local_Resource\\default." + res.lang + ".js";
if(!IsExist(currentFile))
currentFile = folder + "\\Local_Resource\\default.js";
if(!IsExist(currentFile)) throw new Exception("File Not Found");
resourceFiles.push(currentFile);
for(int i = 0; i < resourceFiles.length; i++) Load.js(resourceFiles[i]);
// Get current page name
var pageNameWithoutExtension = "SomePage";
currentFile = currentPageFolderPath + pageNameWithoutExtension + res.lang + ".js" ;
if(!IsExist(currentFile))
currentFile = currentPageFolderPath + pageNameWithoutExtension + ".js" ;
if(!IsExist(currentFile)) throw new Exception("File Not Found");
希望对你有帮助:)
【讨论】:
我唯一不喜欢这种方法的是本地化和开发是紧密耦合的......所以当一个英语(无论默认是什么)字符串被添加时,其余的语言必须是通过代码更新。我宁愿使用某种类型的翻译文件中的工具创建 JSON。仍然是一个很好的代表! 已经完成了与本地化相同的方式,您可以在此查询中看到:***.com/q/53864279/4061006。唯一的问题是您如何将 Global_Resources/default.js 转换为 Global_Resources/default.fr.js ?您使用哪个工具/套件将这些文件转换为所需的语言。因为我也需要这个 您应该在每个键旁边存储一个人类可读的注释,描述字符串的去向和含义,以便您在添加新的时可以为翻译者(或您自己)提供更多上下文语言,而您已经忘记了某些字符串的含义。例如,像localizing Chrome extensions 那样做类似"Create" : "message": "Create", "description": "text on the button that opens the editor with a blank Foo"
的事情。或者创建一个单独的文件来保存这些 cmets。以上是关于字符串和标签本地化和全球化的最佳实践 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章