Łatwe w użyciu ciągi zasobów (.resx) w widoku Razor, ale jak to zrobić w plikach JavaScript? Obecnie ręcznie przekazuję ciągi od widoku maszynki do skryptów w argumencie konstruktora JavaScript, ale chciałbym zrobić to bardziej automatycznie, więc nie muszę przekazywać każdego wymaganego ciągu zasobów.Najlepszy sposób na ujawnienie ciągi zasobów do plików JavaScript w ASP.NET MVC?
Odpowiedz
Można to zrobić w bardziej zgrabny sposób za pomocą AJAX i 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 stronie serwera, znacznie uproszczone, ale masz pomysł:
public ContentResult ResourceLabel(string labelKey) {
return Content(ResourceClass.GetString(labelKey));
}
chciałbym zrobić coś jak następuje:
<script type="text/javascript">
var resourceStrings = {
@foreach (var resource in ViewBag.Resources)
{
{ '@resource.Key' : '@resource.Value' },
}
};
</script>
ta zakłada, że już utworzony słownik klucz/wartości zasobów i ustaw właściwość worka widoku ze słownikiem. Możesz wtedy uzyskać dostęp do tych zasobów jako odnośnik do obiektów javascript.
$('label[name=gender]').html(resourceStrings['gender']);
Można mieć potencjalnie słownika słowników jeśli chcesz uzyskać dostęp do kluczy przez kulturę:
$('label[name=gender]').html(resourceStrings['en_US']['gender']);
Rozwiązanie Użyłem jest użycie Razor utworzyć obiekt JSON, który zawiera wszystkie ciągi zasobów dla danego obszaru zastosowania, np. "Klienci". Tak:
<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()));
pliku zasobów „JsCustomersRes” mogą być umieszczone wraz z szczególny kontroler widzi katalogu lub w udostępnionym katalogu widoku. Powinien mieć "Własne narzędzie" ustawione na "PublicResXFileCodeGenerator" w zaawansowanych właściwościach pliku.
Następnie można uzyskać ciąg zasobów z obiektu json w skrypcie:
var resString = CustomersResourceObj[key];
gdzie „klucz” jest kluczem ciąg ciąg zasobów chcesz. Wystarczy dodać maszynę Razor jako częściowy widok do strony układu lub strony zgodnie z wymaganiami i gotowe!
to dobry sposób na zdobycie zasobów. moja sugestia jest taka, że powinieneś mieć klucze w zasobach, które są używane TYLKO w skryptach (klucz zaczynający się od 'script'), więc nie ładujesz wszystkich kluczy z pliku zasobów (wyobraź sobie, że masz plik zasobów o ponad 1000 kluczy) . , więc masz na chwilę coś takiego: if (! ResEnum.Key.StartsWith ('script')) kontynuuj; –
Dobry pomysł! Dzięki :) – davaus
Moje rozwiązanie opiera się na tym http://codethug.com/2013/08/02/using-net-resources-in-javascript/ i cytując słowa (autor) Tim Larson:
Nie mamy wiele do zrobienia, aby ustalić, co kultura w użyciu. Przeglądarka internetowa, gdy trafi na serwer, zawiera informacje nagłówkowe pokazujące, jakie kultury obsługuje. ASP.Net automatycznie umieszcza tę informację w CultureInfo.CurrentUICulture. Przekazujemy to do metody GetResourceSet , która zwraca zestaw zasobów, który pasuje do bieżących ustawień przeglądarki.
Tak więc, jeśli przeglądarka jest ustawiona na francuski, zasoby francuskie i tylko zasoby francuskie zostaną zwrócone.
Steep 1. Utwórz plik zasobów RLocalizedText.resx do folderu App_GlobalResources.I stwórz wypełnij go całym ciągiem znaków.
Steep 2. Tworzenie 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. Utwórz Index.cshtml widok z ResourcesController
@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
@:[email protected] = "@Html.Raw(
HttpUtility.JavaScriptStringEncode(res.Value.ToString()))";
}
Choose gdzie chcesz go używać.
Strome 4A (układ). Jeśli chcesz używać go na całej stronie, następnie trzeba umieścić ten odniesienie skryptu na _Layout (wspólny View) na @RenderSection
<script src="@Url.Content("~/Resources/Index")"></script>
@RenderSection("scripts", required: false)
Steep 4B (Widok). Jeśli chcesz zobaczyć tylko w niektórych widokach.
@section Scripts
{
<script src="@Url.Content("~/Resources/Index")"></script>
}
Strome 5. Teraz należy go użyć. Wybierz widok, w którym chcesz zobaczyć ciągi w plikach zasobów i umieść ten kod.
@section Scripts
{
<script>
$(document).ready(function() {
alert(Resources.General_Excepcion);
});
</script>
}
To wszystko ludzie! Mam nadzieję, że pomoże to innym!
intellisense nie działa w tym podejściu. – Natiq
Wolę utworzyć obiekt Javascript, który ma wszystkie zasoby jako właściwości. Unikaję też tworzenia częściowego widoku. Zamiast tego przekazuję wymagany język jako parametr skryptu. W ten sposób możesz dodać skrypt w szablonie globalnym zamiast dodawać go na każdej stronie.
Zasadniczo mam pomocnika statyczną klasę z poniższej metody statycznej:
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()
};
}
w projekcie Dodałem następujące Kontroler:
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);
}
}
Zauważ, że dodałem parametr dać globalny obiekt javascript dowolną nazwę. W powyższym przykładzie, mogę przejść do tłumaczenia jak to w JS:
alert(Client.Info_Message);
teraz nazwać ten skrypt, zarejestrować go w domyślnym szablonie (na przykład w ~/Shared/_layout.cshtml
)
<script type="text/javascript" src="~/resources/[email protected](ViewBag.Language)"></script>
Najlepszym Aby to działało, należy utworzyć filtr akcji, aby automatycznie wprowadzić język w ViewData. Można to zrobić tak:
public class LanguageInViewBagAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var controller = filterContext.Controller;
if (controller != null)
controller.ViewBag.Language = Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName;
}
}
Następnie można ozdobić kontrolerów lub czynności z tym w stosownych przypadkach, na przykład:
[LanguageInViewBag]
public class HomeController : Controller
lub zarejestruj jako filtr globalnym /App_start/Filters.cs
Uwaga: Moja implementacja zakłada, że użytkownik ustawił na jedną osobę kulturę użytkownika na Thread.CurrentThread.CurrentCulture
. W ten sposób filtr akcji zna aktualnie wybrany język.
Czy nie utworzymy osobnego żądania dla serwera dla etykiety EACH? –
Będzie; są lepsze odpowiedzi na stronie dla wielu etykiet. Zostawię to tutaj jako dowód koncepcji dla jednej wytwórni. –