ASP NET MVC 5 i18n с использованием кода Надима, но я хочу добавить returnUrl
Я собираюсь включить код, как у меня есть. Я чувствовал, что должен работать, потому что у меня нет волнистых линий. LOL Но я в конечном итоге с петлей перенаправления.
Прежде всего, я получил базовую реализацию из блога Надима Афаны. Я не думаю, что CultureHelper.cs или BaseController.cs могут понадобиться для реализации функциональности returnUrl, но, поскольку они являются частью кода, я включаю их здесь, чтобы вам не приходилось просматривать его веб-сайт, чтобы посмотреть для этого. Я пытался устранить прокрутку и для тебя.
ЗДЕСЬ МОЙ КОД:
Помощники /CultureHelper.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
namespace xxxUSA.Helpers
{
public static class CultureHelper
{
// Valid cultures REMOVED SOME CODES FOR BREVITY
private static readonly List<string> _validCultures = new List<string>
{ "en-AU", "en-BZ", "en-CA", "en-029", "en-IN", "en-IE", "en-JM",
"en-MY", "en-NZ", "en-PH", "en-SG", "en-ZA", "en-TT", "en-GB",
"en-US", "en-ZW", "es-CR", "es-DO", "es-EC", "es-SV", "es-GT",
"es-HN", "es-MX", "es-NI", "es-PA", "es-PY", "es-PE", "es-PR",
"es-ES", "es-US", "es-UY", "es-VE" };
private static readonly List<string> _cultures = new List<string> {
"en-US", // first culture is the DEFAULT
"es", // Spanish NEUTRAL culture
"ar" // Arabic NEUTRAL culture
};
public static bool IsRightToLeft()
{
return
System.Threading.Thread.CurrentThread
.CurrentCulture.TextInfo.IsRightToLeft;
}
public static string GetImplementedCulture(string name)
{
// make sure it's not null
if (string.IsNullOrEmpty(name))
return GetDefaultCulture(); // return Default culture
if (_validCultures.Where(c => c.Equals(name,
StringComparison.InvariantCultureIgnoreCase)).Count() == 0)
return GetDefaultCulture(); // return Default if invalid
if (_cultures.Where(c => c.Equals(name,
StringComparison.InvariantCultureIgnoreCase)).Count() > 0)
return name; // accept it
var n = GetNeutralCulture(name);
foreach (var c in _cultures)
if (c.StartsWith(n))
return c;
return GetDefaultCulture(); // return Default if no match
}
public static string GetDefaultCulture()
{
return _cultures[0]; // return Default culture
}
public static string GetCurrentCulture()
{
return Thread.CurrentThread.CurrentCulture.Name;
}
public static string GetCurrentNeutralCulture()
{
return GetNeutralCulture(Thread.CurrentThread.CurrentCulture.Name);
}
public static string GetNeutralCulture(string name)
{
if (name.Length < 2)
return name;
return name.Substring(0, 2);
}
}
}
Контроллеры /BaseController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Mvc;
using xxxUSA.Helpers;
namespace xxxUSA.Controllers
{
public class BaseController : Controller
{
protected override IAsyncResult BeginExecuteCore(
AsyncCallback callback, object state)
{
string cultureName = null;
// Attempt to read the culture cookie from Request
HttpCookie cultureCookie = Request.Cookies["_culture"];
if (cultureCookie != null)
cultureName = cultureCookie.Value;
else
cultureName = Request.UserLanguages != null &&
Request.UserLanguages.Length > 0 ? Request.UserLanguages[0]
: null; // obtain it from HTTP header AcceptLanguages
// Validate culture name
cultureName = CultureHelper.GetImplementedCulture(cultureName);
// Modify current thread's cultures
Thread.CurrentThread.CurrentCulture = new
System.Globalization.CultureInfo(cultureName);
Thread.CurrentThread.CurrentUICulture =
Thread.CurrentThread.CurrentCulture;
return base.BeginExecuteCore(callback, state);
}
}
}
Хорошо, теперь мы попадаем туда, где я изменил некоторые вещи. Я прокомментирую все, что я добавил
Контроллеры /HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using xxxUSA.Helpers;
using xxxUSA.Models;
namespace xxxUSA.Controllers
{
public class HomeController : BaseController
{
ApplicationDbContext _db = new ApplicationDbContext();
public ActionResult Index()
{
return View();
}
public ActionResult About()
{
return View();
}
public ActionResult Contact()
{
return View();
}
//I ADDED THIS LAST PARAMETER
public ActionResult SetCulture(string culture, string returnUrl)
{
// Validate input
culture = CultureHelper.GetImplementedCulture(culture);
// Save culture in a cookie
HttpCookie cookie = Request.Cookies["_culture"];
if (cookie != null)
cookie.Value = culture; // update cookie value
else
{
cookie = new HttpCookie("_culture");
cookie.Value = culture;
cookie.Expires = DateTime.Now.AddYears(1);
}
Response.Cookies.Add(cookie);
//THIS WORKS
return Redirect(returnUrl);
//THIS DOES NOT
if (!string.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
Теперь код на домашней странице
Views/Home/Index.cshtml
@{
var culture = System.Threading.Thread.CurrentThread
.CurrentUICulture.Name.ToLowerInvariant();
ViewBag.Title = culture;
}
//I ADDED THIS LAST PARAMETER
@helper selected(string c, string culture, string returnUrl)
{
if (c == culture)
{
@:checked="checked"
}
}
@using (Html.BeginForm("SetCulture", "Home"))
{
@Resources.ChooseYourLanguage
<input name="culture" id="en-us" value="en-us"
//I ADDED THIS LAST PARAMETER "About"
type="radio" @selected("en-us", culture, "About") /> English
<input type="Hidden" name="returnUrl" value="About" />
<input name="culture" id="es" value="es"
//I ADDED THIS LAST PARAMETER "About"
type="radio" @selected("es", culture, "About") /> Español
}
//LOTS OF STUFF LOADS HERE LIKE RESOURCE REFERENCES, GRAPHICS, CONTENT,
//NOT IMPORTANT FOR THE IMPLEMENTATION REMOVED FOR BREVITY
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript">
(function ($) {
$("input[type = 'radio']").click(function () {
$(this).parents("form").submit(); // post form
});
})(jQuery);
</script>
}
Поэтому я добавил "About" по той причине, что, если я заставлю его работать, он будет перенаправлен на действие "About" вместо того, чтобы вернуться на ту же самую домашнюю страницу. Это не работает, хотя.
Могу ли я не перегружать флажки @Selected Method, как у меня?
Кроме того, НЕ ВАЖНО СЕЙЧАС, но что, если я хочу добавить это к другим представлениям от других контроллеров, могу ли я включить другой параметр для обозначения контроллера и действия, к которому он должен вернуться, чтобы мне не приходилось повторять код в каждом контроллер?
Я связался с Надимом в твиттере, и он сказал, что проверит это и попробует помочь. Я действительно ценю его работу и, похоже, очень добрый парень. Заранее спасибо за помощь в любом качестве!
Итак, у меня есть страница продуктов / ингредиентов, где у меня есть материал, поступающий из базы данных, вот как я взломал это, чтобы показать правильное поле из базы данных. Это полный взломать.
Просмотров /Products.cshtml
@model IEnumerable<xxxUSA.Models.Ingredient>
@{
var culture = System.Threading.Thread.CurrentThread
.CurrentUICulture.Name.ToLowerInvariant();
ViewBag.Title = culture;
}
@helper selected(string c, string culture)
{
if (c == culture)
{@:checked="checked"}
}
<div class="row">
<div class="large-12 columns">
@using(Html.BeginForm("SetCulture", "Ingredient"))
{
<div class="row">
<div class="large-6 columns">
<label>@Resources.ChooseYourLanguage</label>
<input type="Hidden" name="returnUrl" value="/Prodcuts/" />
<input name="culture" id="en-us" value="en-us" type="radio"
@selected("en-us", culture) /> English
<input name="culture" id="es" value="es" type="radio"
@selected("es", culture) /> Español
</div>
</div>
}
@{ViewBag.Culture = System.Threading.Thread.CurrentThread
.CurrentUICulture.Name.ToLowerInvariant();}
//Here is where the conditional logic hack I use to show one field
//or another from the database based on culture
@if (ViewBag.Culture == "en-us") {
@Html.DisplayFor(modelItem => item.IngredientNameEn)
} else {
@Html.DisplayFor(modelItem => item.IngredientNameEs) }
В основном, используя эту условную логику в любом месте, у меня есть данные на испанском или английском языке. это чертовски хакерски.
2 ответа
Попробуй это:
public ActionResult SetCulture(string culture, string returnUrl)
{
// Validate input
culture = CultureHelper.GetImplementedCulture(culture);
// Save culture in a cookie
HttpCookie cookie = Request.Cookies["_culture"];
if (cookie != null)
cookie.Value = culture; // update cookie value
else
{
cookie = new HttpCookie("_culture");
cookie.Value = culture;
cookie.Expires = DateTime.Now.AddYears(1);
}
Response.Cookies.Add(cookie);
if (!string.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
Я также использую решение Nadeem i18n в проекте. Способ переключения культуры в этом проекте заключается в нажатии на флажки (привязывать теги в тегах изображений). Я добавил returnUrl и получил цикл перенаправления. Чтобы исправить проблему с циклом перенаправления, я сделал несколько изменений в коде и получил следующий код:
Файл: BaseController.cs (добавлен этот метод)
public ActionResult SetCulture(string culture, string returnUrl)
{
// Validate input
culture = CultureHelper.GetImplementedCulture(culture);
RouteData.Values["culture"] = culture;
// Save culture in a cookie
HttpCookie cookie = Request.Cookies["_culture"];
if (cookie != null)
{
// update cookie value
cookie.Value = culture;
}
else
{
cookie = new HttpCookie("_culture");
cookie.Value = culture;
cookie.Expires = DateTime.Now.AddYears(1);
}
Response.Cookies.Add(cookie);
return Redirect(returnUrl);
}
Файл: _layout.cshtml (флаги для выбора культуры):
@{ var daDkUrl = Url.Action("setculture", "base", new { culture = "da-DK", returnUrl = Request.RawUrl }); }
<a href="@daDkUrl">
<img src="~/content/images/flag_da.gif" width="16" height="11" alt="Dansk" />
</a>
|
@{ var enUsUrl = Url.Action("setculture", "base", new { culture = "en-US", returnUrl = Request.RawUrl }); }
<a href="@enUsUrl">
<img src="~/content/images/flag_en.gif" width="16" height="11" alt="English" />
</a>
Наконец, убедитесь, что ваши контроллеры наследуются от BaseController.cs.
public class TestController : BaseController
{
//Code
}