简体   繁体   English

在 ASP.NET MVC 中将资源字符串公开给 JavaScript 文件的最佳方法?

[英]Best way to expose resource strings to JavaScript files in ASP.NET MVC?

It's easy to use resource strings (.resx) in Razor view, but how to do that in JavaScript files?在 Razor 视图中使用资源字符串 (.resx) 很容易,但如何在 JavaScript 文件中使用呢? Currently I'm manually passing strings from Razor view to scripts in JavaScript constructor argument but I would like a way to do this more automatically so I don't have to pass each and every resource string that I need.目前我正在手动将字符串从 Razor 视图传递到 JavaScript 构造函数参数中的脚本,但我想要一种更自动地执行此操作的方法,因此我不必传递我需要的每个资源字符串。

The solution I have used is to use a Razor to create a json object that contains all the resource strings for a given application area eg "Customers".我使用的解决方案是使用 Razor 创建一个 json 对象,该对象包含给定应用程序区域的所有资源字符串,例如“客户”。 Like so:像这样:

<script  type="text/jscript">

@{

    ResourceSet resourceSet = JsCustomersRes.ResourceManager.GetResourceSet(CultureInfo.CurrentUICulture, true, true);
    var sbInitial = " var CustomersResourceObj = {"; 
    var sb = new StringBuilder(sbInitial);
    var resEnum = resourceSet.GetEnumerator(); 
    while (resEnum.MoveNext()) 
    {
        if (sb.ToString() != sbInitial)
        {
            sb.Append(",");
        }
        sb.Append("\"" + resEnum.Key + "\":\"" + resEnum.Value.ToString().Replace("\r\n", "").Replace("\"", "\\\"") + "\"");
    } 
    sb.Append("}");
} 

@(Html.Raw( sb.ToString()));

The resource file "JsCustomersRes" can be placed along with the particular controller views directory or in the shared view directory.资源文件“JsCustomersRes”可以与特定的控制器视图目录或共享视图目录一起放置。 It should have "Custom Tool" set to "PublicResXFileCodeGenerator" in the file advanced properties.它应该在文件高级属性中将“自定义工具”设置为“PublicResXFileCodeGenerator”。

You can then get the resource string from the json object in your script:然后,您可以从脚本中的 json 对象获取资源字符串:

var resString = CustomersResourceObj[key];

where "key" is the key string of the resource string you want.其中“key”是您想要的资源字符串的键字符串。 Just add the Razor as a partial view to your layout page or individual page as you require and that's it!只需根据需要将 Razor 作为部分视图添加到您的布局页面或单个页面,就是这样!

My solution is based on this http://codethug.com/2013/08/02/using-net-resources-in-javascript/ and quoting Tim Larson's (author) words:我的解决方案基于此http://codethug.com/2013/08/02/using-net-resources-in-javascript/并引用 Tim Larson(作者)的话:

We don't have to do much to determine what culture to use.我们不必做太多事情来确定要使用的文化。 The web browser, when it hits the server, includes header information showing what cultures it supports. Web 浏览器在访问服务器时包含显示其支持的文化的标头信息。 ASP.Net automatically puts this information into CultureInfo.CurrentUICulture. ASP.Net 会自动将此信息放入 CultureInfo.CurrentUICulture。 We pass this into the GetResourceSet method, which then returns the resource set that matches the current browser settings.我们将其传递给 GetResourceSet 方法,然后该方法返回与当前浏览器设置匹配的资源集。

Thus, if the browser is set to French, the French resources, and only the French Resources, will be returned.因此,如果浏览器设置为法语,将返回法语资源,并且仅返回法语资源。

Steep 1. Create a resource file RLocalizedText.resx into App_GlobalResources folder.陡峭 1. 在 App_GlobalResources 文件夹中创建资源文件RLocalizedText.resx And create fill it with all the string.并创建用所有字符串填充它。

Steep 2. Create ResourcesController步骤 2. 创建ResourcesController

using System.Web.Mvc;

namespace PortalACA.Controllers
{
    public class ResourcesController : Controller
    {
        // GET: Resources
        public ActionResult Index()
        {
            Response.ContentType = "text/javascript";
            return View();
        }
    }
}

Steep 3. Create Index.cshtml view from ResourcesController陡峭 3. 从 ResourcesController 创建Index.cshtml视图

@using System.Collections
@using System.Globalization
@using System.Resources
@using Resources
@{
    Layout = null;
    // Get a set of resources appropriate to
    // the culture defined by the browser
    ResourceSet resourceSet =
      @RLocalizedText.ResourceManager.GetResourceSet
        (CultureInfo.CurrentUICulture, true, true);
}

// Define the empty object in javascript
var Resources = {};
@foreach (DictionaryEntry res in resourceSet)
{
    // Create a property on the javascript object for each text resource
    @:Resources.@res.Key = "@Html.Raw(
        HttpUtility.JavaScriptStringEncode(res.Value.ToString()))";
}

The choose where you want use it.选择你想要使用它的地方。

Steep 4A (Layout).陡峭的4A(布局)。 If you want use it on whole site, then need put this script reference on _Layout (Shared View) over @RenderSection如果您想在整个站点上使用它,则需要将此脚本引用放在@RenderSection上的_Layout (共享视图)上

<script src="@Url.Content("~/Resources/Index")"></script>
@RenderSection("scripts", required: false)

Steep 4B (View).陡峭的4B(视图)。 If you want to see only in some views.如果您只想在某些视图中查看。

@section Scripts
{
  <script src="@Url.Content("~/Resources/Index")"></script>
}

Steep 5. Now it is the time to use it.陡峭 5. 现在是使用它的时候了。 Select a view where you need see the strings on Resources files and put this code.选择需要查看资源文件字符串的视图并放置此代码。

@section Scripts
{
  <script>
    $(document).ready(function () {
      alert(Resources.General_Excepcion);
    });
  </script>
}

That's all Folks!这就是所有的人! Hope it help others!希望它能帮助别人!

I would do something like the following:我会做类似以下的事情:

<script type="text/javascript">
    var resourceStrings = {
        @foreach (var resource in ViewBag.Resources)
        {
            { '@resource.Key' : '@resource.Value' },
        }
    };
</script>

This assumes that you've created a dictionary of resource key/values and set a view bag property with the dictionary.这假设您已经创建了一个资源键/值字典,并使用该字典设置了一个视图包属性。 You can then access those resources as a javascript object lookup.然后,您可以将这些资源作为 javascript 对象查找来访问。

$('label[name=gender]').html(resourceStrings['gender']);

You could potentially have a dictionary of dictionaries if you wanted to access keys by culture:如果你想按文化访问键,你可能有一个字典字典:

$('label[name=gender]').html(resourceStrings['en_US']['gender']);

I prefer to create a Javascript object that has all the resources as properties.我更喜欢创建一个将所有资源作为属性的 Javascript 对象。 Also I avoid creating a partial view.我也避免创建局部视图。 Instead I pass the required language as a parameter to the script.相反,我将所需的语言作为参数传递给脚本。 This way you can add the script in a global template, instead of adding it in each page.这样您就可以在全局模板中添加脚本,而不是在每个页面中添加它。

Basically I have a helper static class with the following static method:基本上我有一个带有以下静态方法的辅助静态类:

    public static JavaScriptResult JavascriptResources(ResourceManager manager, string resourceObjectName, CultureInfo culture)
    {
        ResourceSet resourceSet = manager.GetResourceSet(culture, true, true);

        StringBuilder sb = new StringBuilder();

        sb.AppendFormat("var {0}=new Object();", resourceObjectName);

        var enumerator = resourceSet.GetEnumerator();
        while (enumerator.MoveNext())
        {
            sb.AppendFormat("{0}.{1}='{2}';", resourceObjectName, enumerator.Key,
                System.Web.HttpUtility.JavaScriptStringEncode(enumerator.Value.ToString()));
        }

        return new JavaScriptResult()
        {
            Script = sb.ToString()
        };
    }

In the project I've added the following controller:在项目中,我添加了以下控制器:

public class ResourcesController : Controller
{
    [OutputCache(Duration = 36000, VaryByParam = "lang")]
    // Duration can be many hours as embedded resources cannot change without recompiling.
    // For the clients, I think 10 hours is good.
    public JavaScriptResult Index(string lang)
    {
        var culture = new CultureInfo(lang);
        return Helpers.JavascriptResources(Resources.Client.ResourceManager,
            "Client", culture);
    }
}

Note that I have added a parameter give the global javascript object any name you want.请注意,我添加了一个参数,为全局 javascript 对象提供您想要的任何名称。 In the example above, I could access the translations like this in JS:在上面的例子中,我可以在 JS 中访问这样的翻译:

alert(Client.Info_Message);

Now to call this script, I register it in the default template (for example in ~/Shared/_layout.cshtml )现在要调用这个脚本,我在默认模板中注册它(例如在~/Shared/_layout.cshtml

<script type="text/javascript" src="~/resources/?lang=@(ViewBag.Language)"></script>

The best way for this to work, is to create an action filter to automatically enter the language in the ViewData.最好的方法是创建一个动作过滤器来自动在 ViewData 中输入语言。 This could be done like this:这可以像这样完成:

public class LanguageInViewBagAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var controller = filterContext.Controller;
        if (controller != null)
            controller.ViewBag.Language = Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName;
    }
}

You can then decorate controllers or actions with it where applicable, for example:然后,您可以在适用的情况下用它装饰控制器或动作,例如:

[LanguageInViewBag]
public class HomeController : Controller

or register as a global filter in /App_start/Filters.cs或在/App_start/Filters.cs注册为全局过滤器

Note: My implementation assumes you set per request the Thread.CurrentThread.CurrentCulture to the user's culture.注意:我的实现假设您为每个请求将Thread.CurrentThread.CurrentCulture设置为用户的文化。 This way the actionfilter knows the currently selected language.这样 actionfilter 就知道当前选择的语言。

Create an action which expose your Resource Set to json创建一个将您的资源集公开给 json 的操作

public class HomeController: Controller {

   [Route("localization.js")]
   public ActionResult Localization()
   {
       ResourceSet resourceSet = Globalization.Resources.ResourceManager.GetResourceSet(
                                       CultureInfo.CurrentUICulture, true, true);
       var result = resourceSet.Cast<DictionaryEntry>()
           .ToDictionary(x => x.Key.ToString(),
                    x => x.Value.ToString());

       return View((object)(JsonConvert.SerializeObject(result)));
   }

}

add ~/Views/Home/localization.cshtml file with the content添加包含内容的~/Views/Home/localization.cshtml文件

@model string
@{ 
    Layout = null;
}
var Resources = @Html.Raw(Model);

In Web.config , add the handler for localization.jsWeb.config ,为localization.js添加处理程序

 <system.webServer>
   <handlers>
     <add name="Localization" path="*/localization.js" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
   </handlers>
 </system.webServer>

Call the action in your _Layout.cshtml or wherever you want to expose your Resources在您的_Layout.cshtml或任何您想公开资源的地方调用该操作

<script type="text/javascript">
    @(Html.Action("Localization", "Home"))
</script>

Result结果

<script type="text/javascript">
    var Resources = {"HelloWorld" : "こんにちは世界", "NiceJob": "いいね!" };
    //Sample usage
    console.log(Resources.HelloWorld);
    console.log(Resources.NiceJob);
</script>

You could do that in a more graceful way using AJAX and a JSON ActionResult.您可以使用 AJAX 和 JSON ActionResult 以更优雅的方式做到这一点。

<button />
<label for="gender"></label>

<script type="text/javascript">
    $("button").click(function () {
        $('label[for=gender]').load('@Url.Action("ResourceLabel", new { labelKey = "Gender" })');
    });
</script>

And server side, greatly simplified, but you get the idea:和服务器端,大大简化,但你明白了:

public ContentResult ResourceLabel(string labelKey) {
    return Content(ResourceClass.GetString(labelKey));
}

All solutions, better or worse, have been mentioned.已经提到了所有解决方案,无论好坏。 Just for completion I want to propose another solution: Do not set text from within Javascript.只是为了完成,我想提出另一个解决方案:不要在 Javascript 中设置文本。

Adding words from Javascript to the page that are not directly loaded from the server, is as if you would write css in an html file.将来自 Javascript 的单词添加到页面,而不是直接从服务器加载,就像在 html 文件中编写 css 一样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在 javascript 文件中使用 ASP.NET 资源字符串 - Use ASP.NET Resource strings from within javascript files 使用Asp.Net MVC在javascript中删除硬编码字符串的最佳方法 - Best way to remove hardcoded string in javascript with Asp.Net MVC 在ASP.NET MVC中处理日期的最佳方法-Javascript应用程序 - The best way to deal with dates in a ASP.NET MVC - Javascript application 如何从JavaScript文件中使用ASP.NET Resource(.resx)字符串 - How to use ASP.NET Resource(.resx) strings from within javascript files 将JavaScript写入ASP.NET的最佳方法 - Best way to write javascript to ASP.NET 在asp.net mvc中添加JavaScript文件 - Add JavaScript files in asp.net mvc Asp.net MVC - 加载JavaScript文件 - Asp.net MVC - load JavaScript files Javascript / ASP.NET MVC 4-在Javascript中使用C#字符串 - Javascript / ASP.NET MVC 4 - Using C# Strings in Javascript 与asp.net MVC3和淘汰js库一起使用的最佳ViewModel javascript文件组织是什么? - What's the best ViewModel javascript files organization, working with asp.net MVC3 and knockout js library? 筛选只能通过ASP.NET MVC中的javascript过滤的数据库记录列表的最佳方法是什么 - What is the best way to filter a list of database records that can only be filtered through javascript in ASP.NET MVC
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM