我目前正在使用.resx
文件管理.NET的服务器端资源。
我正在处理的应用程序还允许开发人员将JavaScript插入各种事件处理程序以进行客户端验证等。对我来说,本地化我的JavaScript消息和字符串的最佳方法是什么?
理想情况下,我希望将字符串存储在.resx
文件中,以使其与其他本地化资源保持一致。
我愿意接受建议。
答案 0 :(得分:25)
基本JavaScript对象是关联数组,因此可以轻松地用于存储键/值对。因此,使用JSON,您可以为每个字符串创建一个对象,如下所示:
var localizedStrings={
confirmMessage:{
'en/US':'Are you sure?',
'fr/FR':'Est-ce que vous êtes certain?',
...
},
...
}
然后你可以得到每个字符串的语言环境版本:
var locale='en/US';
var confirm=localizedStrings['confirmMessage'][locale];
答案 1 :(得分:13)
灵感来自SproutCore您可以设置属性 字符串:
'Hello'.fr = 'Bonjour';
'Hello'.es = 'Hola';
然后根据您的区域设置简单地吐出正确的本地化:
var locale = 'en';
alert( message[locale] );
答案 2 :(得分:10)
经过Google搜索并对所提供的大多数解决方案不满意,我刚刚找到了一个使用T4 templates的惊人/通用解决方案。您可以在此处阅读Jochen van Wylick完整的帖子:
Using T4 for localizing JavaScript resources based on .resx files
主要优点是:
缺点:
这种解决方案的缺点当然是大小的 .js文件可能会变得非常大。但是,因为它被缓存了 浏览器,我们不认为这是我们的应用程序的问题。然而 - 此缓存还可能导致浏览器无法找到从代码调用的资源。
这是如何运作的?
基本上他定义了一个指向.resx文件的T4模板。使用一些C#代码,他遍历每个资源字符串并将其添加到JavaScript纯键值属性,然后在名为Resources.js
的单个JavaScript文件中输出(如果您愿意,可以调整名称)。
T4模板 [相应更改指向您的.resx文件位置]
<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ assembly name="System.Windows.Forms" #>
<#@ import namespace="System.Resources" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.IO" #>
<#@ output extension=".js"#>
<#
var path = Path.GetDirectoryName(Host.TemplateFile) + "/../App_GlobalResources/";
var resourceNames = new string[1]
{
"Common"
};
#>
/**
* Resources
* ---------
* This file is auto-generated by a tool
* 2012 Jochen van Wylick
**/
var Resources = {
<# foreach (var name in resourceNames) { #>
<#=name #>: {},
<# } #>
};
<# foreach (var name in resourceNames) {
var nlFile = Host.ResolvePath(path + name + ".nl.resx" );
var enFile = Host.ResolvePath(path + name + ".resx" );
ResXResourceSet nlResxSet = new ResXResourceSet(nlFile);
ResXResourceSet enResxSet = new ResXResourceSet(enFile);
#>
<# foreach (DictionaryEntry item in nlResxSet) { #>
Resources.<#=name#>.<#=item.Key.ToString()#> = {
'nl-NL': '<#= ("" + item.Value).Replace("\r\n", string.Empty).Replace("'","\\'")#>',
'en-GB': '<#= ("" + enResxSet.GetString(item.Key.ToString())).Replace("\r\n", string.Empty).Replace("'","\\'")#>'
};
<# } #>
<# } #>
在表单/视图方面
要获取正确的翻译,如果您使用的是WebForms,请在主文件中添加:
<script type="text/javascript">
var locale = '<%= System.Threading.Thread.CurrentThread.CurrentCulture.Name %>';
</script>
<script type="text/javascript" src="/Scripts/Resources.js"></script>
如果你正在使用ASP.NET MVC(像我一样),你可以这样做:
<script type="text/javascript">
// Setting Locale that will be used by JavaScript translations
var locale = $("meta[name='accept-language']").attr("content");
</script>
<script type="text/javascript" src="/Scripts/Resources.js"></script>
我从Scott Hanselman发表的这篇精彩文章中得到的MetaAcceptLanguage
助手:
public static IHtmlString MetaAcceptLanguage<T>(this HtmlHelper<T> html)
{
var acceptLanguage =
HttpUtility.HtmlAttributeEncode(
Thread.CurrentThread.CurrentUICulture.ToString());
return new HtmlString(
String.Format("<meta name=\"{0}\" content=\"{1}\">", "accept-language",
acceptLanguage));
}
使用
var msg = Resources.Common.Greeting[locale];
alert(msg);
答案 3 :(得分:4)
我会使用对象/数组表示法:
var phrases={};
phrases['fatalError'] ='On no!';
然后您可以交换JS文件,或使用Ajax调用重新定义您的短语列表。
答案 4 :(得分:4)
使用附属程序集(而不是resx文件),您可以枚举服务器上您知道语言的所有字符串,从而生成仅包含正确语言字符串的Javascript对象。
这样的东西对我们有用(VB.NET代码):
Dim rm As New ResourceManager([resource name], [your assembly])
Dim rs As ResourceSet =
rm.GetResourceSet(Thread.CurrentThread.CurrentCulture, True, True)
For Each kvp As DictionaryEntry In rs
[Write out kvp.Key and kvp.Value]
Next
然而,遗憾的是,我们还没有为.resx文件找到一种方法。
答案 5 :(得分:4)
JSGettext做得非常出色 - 使用后端几乎任何语言动态加载GNU Gettext .po文件。谷歌用“使用Gettext和PHP进行动态Javascript本地化”来查找JSGettext与PHP的演练(我发布了链接,但是这个愚蠢的网站不会让我叹息......)
修改:this应为链接
答案 6 :(得分:3)
有一个用于本地化JavaScript应用程序的库: https://github.com/wikimedia/jquery.i18n
它可以进行参数替换,支持性别(聪明的他/她处理),数字(聪明的复数处理,包括具有多个复数形式的语言),以及某些语言需要的自定义语法规则。
字符串存储在JSON文件中。
唯一的要求是jQuery。
答案 7 :(得分:2)
我为运行HTML5的移动应用本地化了JavaScript:
1.为每种语言处理一组资源文件,称为英语的“en.js”。每个包含应用程序的不同字符串如下:
var localString = {
appName: "your app name",
message1: "blah blah"
};
2.使用Lazyload根据应用的语言环境语言加载正确的资源文件:https://github.com/rgrove/lazyload
3.通过查询字符串传递语言代码(因为我使用PhoneGap从Android启动html文件)
4.然后我编写了以下代码以动态加载适当的资源文件:
var lang = getQueryString("language");
localization(lang);
function localization(languageCode) {
try {
var defaultLang = "en";
var resourcesFolder = "values/";
if(!languageCode || languageCode.length == 0)
languageCode = defaultLang;
// var LOCALIZATION = null;
LazyLoad.js(resourcesFolder + languageCode + ".js", function() {
if( typeof LOCALIZATION == 'undefined') {
LazyLoad.js(resourcesFolder + defaultLang + ".js", function() {
for(var propertyName in LOCALIZATION) {
$("#" + propertyName).html(LOCALIZATION[propertyName]);
}
});
} else {
for(var propertyName in LOCALIZATION) {
$("#" + propertyName).html(LOCALIZATION[propertyName]);
}
}
});
} catch (e) {
errorEvent(e);
}
}
function getQueryString(name)
{
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regexS = "[\\?&]" + name + "=([^&#]*)";
var regex = new RegExp(regexS);
var results = regex.exec(window.location.href);
if(results == null)
return "";
else
return decodeURIComponent(results[1].replace(/\+/g, " "));
}
5.从html文件中我引用字符串如下:
span id="appName"
答案 8 :(得分:1)
嗯,我认为你可以考虑这个。英语 - 西班牙语示例:
写下2张Js脚本,就像那样:
en-GB.js
lang = {
date_message: 'The start date is incorrect',
...
};
es-ES.js
lang = {
date_message: 'Fecha de inicio incorrecta',
...
};
服务器端 - 代码隐藏:
Protected Overrides Sub InitializeCulture()
Dim sLang As String
sLang = "es-ES"
Me.Culture = sLang
Me.UICulture = sLang
Page.ClientScript.RegisterClientScriptInclude(sLang & ".js", "../Scripts/" & sLang & ".js")
MyBase.InitializeCulture()
End Sub
根据当前用户的选择,sLang可能是“en-GB”......
Javascript调用:
alert (lang.date_message);
我认为这很有效。
答案 9 :(得分:0)
扩展binaryus.myopenid.com的答案:让你的代码写出一个包含所有必需字符串的JS数组的文件,然后在其他JS代码之前加载适当的文件/脚本。
答案 10 :(得分:-1)
MSDN
way of doing it,基本上是:
您为每种受支持的语言和文化创建单独的脚本文件。在每个脚本文件中,您包含一个JSON格式的对象,其中包含该语言和文化的本地化资源值。
我不能告诉你问题的最佳解决方案,但恕我直言,这是最糟糕的做法。至少现在你知道怎么不这样做。
答案 11 :(得分:-1)
我们使用MVC并简单地创建了一个控制器动作来返回一个本地化的字符串。我们在会话中维护用户的文化,并在任何调用之前设置线程文化以检索语言字符串,AJAX或其他。这意味着我们总是返回一个本地化的字符串。
我承认,这不是最有效的方法,但在javascript中获取本地化字符串很少需要,因为大多数本地化都是在我们的部分视图中完成的。
<强>的Global.asax.cs 强>
protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
if (Context.Handler is IRequiresSessionState || Context.Handler is IReadOnlySessionState)
{
// Set the current thread's culture
var culture = (CultureInfo)Session["CultureInfo"];
if (culture != null)
{
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
}
}
}
控制器操作
public string GetString(string key)
{
return Language.ResourceManager.GetString(key);
}
<强>的Javascript 强>
/*
Retrieve a localized language string given a lookup key.
Example use:
var str = language.getString('MyString');
*/
var language = new function () {
this.getString = function (key) {
var retVal = '';
$.ajax({
url: rootUrl + 'Language/GetString?key=' + key,
async: false,
success: function (results) {
retVal = results;
}
});
return retVal;
}
};