2013-04-20 15 views
18

È facile utilizzare le stringhe di risorse (.resx) nella visualizzazione Razor, ma come farlo nei file JavaScript? Attualmente sto passando manualmente le stringhe dalla vista Razor agli script nell'argomento del costruttore di JavaScript, ma vorrei un modo per farlo in modo più automatico in modo da non dover passare ogni singola stringa di risorse di cui ho bisogno.Il modo migliore per esporre le stringhe di risorse ai file JavaScript in ASP.NET MVC?

risposta

0

È possibile farlo in modo più agevole utilizzando AJAX e 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> 

E lato server, molto semplificato, ma si ottiene l'idea:

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

Non creare una richiesta separata per il server per OGNI etichetta? –

+0

Lo farà; ci sono risposte migliori nella pagina per più etichette. Lo lascerò qui come prova di concetto per una singola etichetta. –

2

vorrei fare qualcosa di simile al seguente:

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

Questo presuppone che hai creato un dizionario di chiavi/valori di risorse e imposta una proprietà view bag con il dizionario. È quindi possibile accedere a tali risorse come una ricerca di oggetti javascript.

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

si potrebbe avere un dizionario di dizionari, se si voleva accedere alle chiavi dalla cultura:

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

La soluzione che ho usato è quello di usare un rasoio per creare un oggetto JSON che contiene tutte le stringhe di risorse per una determinata area di applicazione, ad esempio "Clienti". In questo modo:

<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())); 

il file di risorse "JsCustomersRes" può essere posizionato con il controller particolare vede directory o nella directory condivisa. Dovrebbe avere lo "Strumento personalizzato" impostato su "PublicResXFileCodeGenerator" nelle proprietà avanzate del file.

È possibile quindi ottenere la stringa di risorsa dall'oggetto JSON nello script:

var resString = CustomersResourceObj[key]; 

dove "chiave" è la stringa chiave della stringa di risorsa che si desidera. Basta aggiungere il Rasoio come vista parziale alla pagina del layout o alla singola pagina come richiesto e il gioco è fatto!

+0

questo è un buon modo per ottenere le risorse. il mio suggerimento è che dovresti avere le chiavi nelle risorse che sono utilizzate SOLO negli script (che iniziano con 'script'), in modo che tu non carichi tutte le chiavi dal file di risorse (immagina di avere un file di risorse di oltre 1000 chiavi) . quindi nel frattempo avresti qualcosa di simile: if (! ResEnum.Key.StartsWith ('script')) continua; –

+0

Buona idea! Grazie :) – davaus

3

La mia soluzione è basata su questa http://codethug.com/2013/08/02/using-net-resources-in-javascript/ e citando (autore) le parole di Tim Larson:

Non abbiamo a che fare molto per determinare quali cultura da usare. Il browser web , quando raggiunge il server, include le informazioni di intestazione che mostrano quali culture supporta. ASP.Net inserisce automaticamente queste informazioni in CultureInfo.CurrentUICulture. Passiamo questo nel metodo GetResourceSet , che restituisce quindi il set di risorse che corrisponde alle impostazioni correnti del browser.

Pertanto, se il browser è impostato su francese, le risorse francesi e solo le risorse francesi verranno restituite.

Steep 1. Creare un file di risorse RLocalizedText.resx nella cartella App_GlobalResources.E creare riempirlo con tutta la stringa.

Steep 2. Creare 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. Creare Index.cshtml vista dalla 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()))"; 
}

L'scegliere dove si desidera utilizzarlo.

Steep 4A (Layout). Se si desidera utilizzare su tutto il sito, quindi necessario mettere questo riferimento script su _Layout (Shared View) nel corso @RenderSection

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

ripida 4B (View). Se vuoi vedere solo in alcune viste.

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

Ripida 5. Ora è il momento di usarlo. Seleziona una vista in cui è necessario vedere le stringhe sui file Risorse e inserire questo codice.

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

Questo è tutto gente! Spero che aiuti gli altri!

+0

intellisense non funziona in questo approccio. – Natiq

1

Preferisco creare un oggetto Javascript che abbia tutte le risorse come proprietà. Inoltre evito di creare una vista parziale. Invece passo la lingua richiesta come parametro per lo script. In questo modo puoi aggiungere lo script in un modello globale, invece di aggiungerlo in ogni pagina.

Fondamentalmente ho una classe statica di supporto con il seguente metodo statico:

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() 
     }; 
    } 

Nel progetto ho aggiunto il seguente 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); 
    } 
} 

Si noti che ho aggiunto un dare parametro l'oggetto javascript globale qualsiasi nome tu voglia. Nell'esempio di cui sopra, ho potuto accedere le traduzioni come questo in JS:

alert(Client.Info_Message); 

Ora per chiamare questo script, mi iscrivo nel modello predefinito (per esempio in ~/Shared/_layout.cshtml)

<script type="text/javascript" src="~/resources/[email protected](ViewBag.Language)"></script> 

La migliore modo per farlo funzionare, è quello di creare un filtro azione per inserire automaticamente la lingua nel ViewData. Ciò potrebbe essere fatto in questo modo:

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

È possibile poi decorare controllori o azioni con esso se del caso, ad esempio:

[LanguageInViewBag] 
public class HomeController : Controller 

o registrati come filtro globale nel /App_start/Filters.cs

Nota: La mia implementazione presuppone che tu abbia impostato per richiesta lo Thread.CurrentThread.CurrentCulture nella cultura dell'utente. In questo modo actionfilter conosce la lingua attualmente selezionata.

Problemi correlati