How do I get a custom localized string in the front end? - localization

I'm having trouble accessing localizations, the value always appears in the default language.
I have two resource files in App_GlobalResources:
Resource.resx contains a string with the name "Hello" and the value of "World".
Resource.fr.resx contains a string with the name "Hello" and the value of "Monde"
In my Razor template:
<lang:string key="Resource, Resources.Resource.Hello" xmlns:lang="http://www.composite.net/ns/localization/1.0" />
"World" is always displayed, never "Monde", even when viewing the page in French.
In a vanilla asp.net website template, with the same resources, the following code within a Razor template displays "Monde"
String cultureInfo = "fr-CA";
System.Threading.Thread.CurrentThread.CurrentCulture =
System.Globalization.CultureInfo.CreateSpecificCulture(cultureInfo);
System.Threading.Thread.CurrentThread.CurrentUICulture = new
System.Globalization.CultureInfo(cultureInfo);
Response.Write(ObjectInfo.Print(Resources.Resource.Hello));
However, within C1 it results in "World".
How should I be going about this?
Thanks!

The <lang:string construct is mainly meant for XSLT templates and functions where you can't as easily fallback to calling c# code directly as in Razor.
Have you tried printing out the resource on your Razor template like this instead #Resources.Resource.Hello ?

Related

A correct way to save html to database and then display it on the page in ASP.NET application

The question is all about encoding.
Currently, I have the following pipeline for html that user produces.
A user is presented with a ckeditor WYSIWYG editor on the page via AngularJS wrapper.
User inputs some text, formats it, this results in html generated in DOM.
Then I use Angular to POST ckeditors contents to ASP.NET MVC Endpoint, where content is automatically wrapped into a string parameter of the action.
That generated string is assigned to a string property of Entity Framework Entity object and saved via DbContext to a database.
Then, to display it, I retrieve entity from Db via DbContext, get that html in string variable in controller code, where I assign it to a View Model for Razor View.
During Razor rendering the string property of the model with html in it is put on the page via #Html.Raw(Model.HtmlMarkupPropery) helper call.
Sometimes I see diamonds with question marks instead of cyrillic (or any two byte) characters, therefore I suspect some encoding problems along the way.
Please let me know where I am not Encoding/Decoding correctly (if any).

How to display the array index number in an editor template

In my model I have a List property of a complex type called EventField.
I created an editor template, which works fine using:
#Html.EditorFor(e => e.EventField)
My question is, within that Editor template I want to pick out the index/sequence number on its own, as a number. This index will simply be added into the template as a data attribute so I can pick it up using javascript.
A couple of answer are out there that don't suffice:
#html.IdFor - outputs the whole name e.g Name[0].other
here - you can't pass through the model name "EventField" this way.
Is there a simple method/function/helper that will give me access to that Index, without having to change how I call the Editor template?
How about:
#using System
#using System.Text.RegularExpressions
var i = Convert.ToInt32(Regex.Matches(
ViewData.TemplateInfo.HtmlFieldPrefix,
#"\[([0-9]+)?\]")[0].Groups[1].ToString());

ViewBag in JQuery

I am using ViewBag value as follows :
var date = "#ViewBag.fromDateForEditMode"
$('#FromDate').val(date);
All I am getting is #ViewBag.fromDateForEditMode and no value.
The Razor engine doesn't execute when MVC is rendering an HTML file, so nothing will parse #ViewBag.fromDateForEditMode and replace it with the ViewBag property value :)
The problem that you are having is that you are trying to enclose the #ViewBag.fromDateForEditMode in quotes. When you do that within your jquery function, this causes the browser jquery processor to evaluate it as a literal string at the time the script is called, rather than allowing your razor engine to evaluate the ViewBag contents at the time the page is loaded.
To get around this issue, use:
var startDate = new Date(#ViewBag.StartDate.Year.ToString(), #ViewBag.StartDate.Month.ToString() -1, #ViewBag.StartDate.Day.ToString());
This will allow the razor engine to evaluate the ViewBag contents before the jquery script is executed.

ASP .NET MVC localization when dynamic variables are included?

Consider the following string if I need to localize it:
You need to write <b>#ViewBag.CharacterAmount</b> characters to be able to
hand-in this homework. You're still missing <b id="charactersRemaining">
#ViewBag.CharacterAmount</b> characters to reach this limit.
What would be the best approach? Using string.Format is a bit complex, since ASP .NET MVC escapes HTML code, and besides, I'd rather be free of HTML code in my resource files. However, I still need to be able to refer to those values inside the b tags from JavaScript.
Any ideas? What is your approach to this when you do localization?
You could write a custom helper:
public static class ResourcesExtensions
{
public static IHtmlString Resource(this HtmlHelper htmlHelper, string message, params object[] args)
{
var parameters = args.Select(x => htmlHelper.Encode(x)).ToArray();
return new HtmlString(string.Format(message, parameters));
}
}
As you can see the HTML helper encodes only the values. We have full control over the rest of the message because it is in the resources file and we suppose that it is valid HTML, so no problem with XSS.
and then have a resources file to your project which will contain for example the following key:
MyMessage = You need to write <b>{0}</b> characters to be able to hand-in this homework. You're still missing <b id="charactersRemaining">{1}</b> characters to reach this limit.
and then don't forget to mark this resources file with the PublicResXFileCodeGenerator custom tool so that Visual Studio generates a public class that will allow you to access the properties in the view.
and finally in the view:
#Html.Resource(Resources.MyMessage, (int)ViewBag.CharacterAmount, (int)ViewBag.CharacterAmount)
The reason you need to cast is because extension method cannot dispatch dynamic arguments. But obviously that's not a problem at all because you shouldn't be using ViewBag/ViewData but you should be using view models and strongly typed view models so in your real code you will have:
#Html.Resource(Resources.MyMessage, Model.CharacterAmount, Model.CharacterAmount)
One downside with this approach is that we have moved some markup in the resources file which unfortunately might render the views a little less understandable and when we need to modify it, we should do this in all localized versions.
Another approach of course consists into putting in your resources file every distinct part of this markup and then:
#Resources.YouNeedToWrite <b>ViewBag.CharacterAmount</b> #Resources.StillMissing
<b id="charactersRemaining">ViewBag.CharacterAmount</b> #(Resources.ToReachLimit).

Returning the text of a Partial

Part of my MVC application includes a wiki. As well as the standard wiki formatting there are a number of special tags for rendering data into templates. When parsing these tags it gets the data from the repository, instantiates a viewmodel and renders it to a partial, this partial then gets inserted into the markup replacing the original tag. The finalised markup itself is rendered as part of a DisplayFor in any properties with the relevant UIHint.
The relevant part of the code is:
private static void MatchSpecial(WikiHelper wh)
{
wh.match = SpecialTagRegex.Match(wh.sb.ToString());
while (wh.match.Success)
{
wh.sb.Remove(wh.match.Index, wh.match.Length);
string[] args = wh.match.Groups[2].Value.Split('|');
switch (wh.match.Groups[1].Value.ToUpperInvariant())
{
case "IMAGE":
string imageid;
imageid = args[0];
Image i = baserepo.imagerepo.GetImage(imageid);
ViewModels.ImageViewModel ivm = new ViewModels.ImageViewModel(i, args);
wh.sb.Insert(wh.match.Index, wh.Html.Partial("ImageViewModel",ivm));
break;
}
wh.match = SpecialTagRegex.Match(wh.sb.ToString(), ws.end);
}
}
The relevant members of WikiHelper are:
wh.sb - StringBuilder containing the markup
wh.html - the HtmlHelper from the main view
wh.match - holds the current regex matches
In MVC2 this worked fine. I'm now in the process of upgrading to MVC3 and the Razor ViewEngine. Despite the fact that Html.Partial is supposed to return the MvcHtmlString of the partial it is instead returning an empty string and writing the content directly into the response, which has the result of all similarly templated elements appearing at the very top of the HTML file (even before anything in my layout file).
Given the symptoms you are describing, I suspect that you are directly writing to the response stream somewhere in your custom helpers. So wherever you are outputing to the response make sure you replace:
htmlHelper.ViewContext.HttpContext.Response.Write("some string");
with:
htmlHelper.ViewContext.Writer.Write("some string");
Writing directly to the response stream worked in WebForms view engine because it is legacy from classic WebForms where this was how things were supposed to work. In ASP.NET MVC though this is incorrect. It worked but is incorrect. All helpers should be writing to ViewContext.Writer instead. Razor writes things into temporary buffers which are then flushed to the response. It uses an inside-out rendering.

Resources