42

我目前正在使用.resx文件来管理 .NET 的服务器端资源。

我正在处理的应用程序还允许开发人员将 JavaScript 插入到各种事件处理程序中以进行客户端验证等。对我来说本地化 JavaScript 消息和字符串的最佳方法是什么?

理想情况下,我想将字符串存储在.resx文件中,以将它们与其他本地化资源一起保存。

我愿意接受建议。

4

12 回答 12

27

一个基本的 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];
于 2008-09-19T17:53:07.007 回答
13

SproutCore启发您可以设置字符串的属性:

'Hello'.fr = 'Bonjour';
'Hello'.es = 'Hola';

然后根据您的语言环境简单地吐出正确的本地化:

var locale = 'en';
alert( message[locale] );
于 2008-09-19T18:06:52.777 回答
11

在谷歌搜索了很多并且对提供的大多数解决方案不满意之后,我刚刚找到了一个使用T4 模板的惊人/通用解决方案。您可以在此处阅读Jochen van Wylick的完整帖子:

使用 T4 本地化基于 .resx 文件的 JavaScript 资源

主要优点是:

  1. 只有 1 个管理资源的地方(即 .resx 文件)
  2. 支持多种文化
  3. 利用 IntelliSense - 允许代码完成

缺点:

这个解决方案的缺点当然是 .js 文件的大小可能会变得非常大。但是,由于它被浏览器缓存,我们不认为这对我们的应用程序来说是个问题。但是 - 这种缓存也可能导致浏览器找不到从代码调用的资源。


这是如何工作的?

基本上,他定义了一个指向您的 .resx 文件的 T4 模板。使用一些 C# 代码,他遍历每个资源字符串并将其添加到 JavaScript 纯键值属性,然后在一个名为的 JavaScript 文件中输出Resources.js(如果您愿意,可以调整名称)。


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>

MetaAcceptLanguage我从 Scott Hanselman 的这篇很棒的帖子中得到的帮助:

ASP.NET MVC 3、JavaScript 和 jQuery 中的全球化、国际化和本地化 - 第 1 部分

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);
于 2013-02-08T22:15:01.563 回答
4

我会使用对象/数组表示法:

var phrases={};
phrases['fatalError'] ='On no!';

然后您可以只交换 JS 文件,或使用 Ajax 调用来重新定义您的短语列表。

于 2008-09-19T17:49:16.827 回答
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 文件执行此操作的方法。

于 2008-11-10T15:53:40.640 回答
4

JSGettext 做得很好——在后端使用几乎任何语言动态加载 GNU Gettext .po 文件。谷歌“使用 Gettext 和 PHP 进行动态 Javascript 本地化”以找到使用 PHP 的 JSGettext 的演练(我会发布链接,但这个愚蠢的网站不会让我,叹息......)

编辑应该是链接

于 2009-05-29T14:26:37.653 回答
3

有一个用于本地化 JavaScript 应用程序的库: https ://github.com/wikimedia/jquery.i18n

可以做参数替换,支持性别(巧妙处理他/她)、数字(巧妙处理复数,包括有多个复数形式的语言),以及一些语言需要的自定义语法规则。

字符串存储在 JSON 文件中。

唯一的要求是 jQuery。

于 2012-11-15T07:01:58.047 回答
2

嗯,我觉得你可以考虑这个。英语-西班牙语示例:

编写 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

你知道,俚语可能是“en-GB”,这取决于当前用户的选择......

Javascript调用:

alert (lang.date_message);

我认为它很有效,非常简单。

于 2014-10-17T10:00:27.717 回答
2

我为运行 HTML5 的移动应用程序执行了以下操作来本地化 JavaScript:

1.为每种语言创建了一组资源文件,将它们称为英语的“en.js”。每个都包含应用程序的不同字符串,如下所示:


        var localString = {
        appName: "your app name",
        message1: "blah blah"
      };

2.使用Lazyload根据应用的locale语言加载合适的资源文件: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"
于 2011-08-21T23:42:35.230 回答
0

扩展diodeus.myopenid.com的答案:让你的代码写出一个包含所有必需字符串的JS数组的文件,然后在其他JS代码之前加载适当的文件/脚本。

于 2008-09-19T17:52:38.880 回答
-1

MSDN这样做的方式,基本上是:

您为每种支持的语言和文化创建一个单独的脚本文件。在每个脚本文件中,您都包含一个 JSON 格式的对象,其中包含该语言和文化的本地化资源值。

我无法告诉您问题的最佳解决方案,但恕我直言,这是最糟糕的方法。至少现在你知道如何不去做。

于 2010-03-22T01:43:50.907 回答
-1

我们使用 MVC 并简单地创建了一个控制器操作来返回一个本地化的字符串。我们在会话中维护用户的文化,并在任何调用检索语言字符串、AJAX 或其他方式之前设置线程文化。这意味着我们总是返回一个本地化的字符串。

我承认,这不是最有效的方法,但很少需要在 javascript 中获取本地化字符串,因为大多数本地化都是在我们的局部视图中完成的。

全球.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;
    }
};
于 2014-06-27T21:24:52.877 回答