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 &nbsp;&nbsp;

<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>
            &nbsp;&nbsp;|&nbsp;&nbsp;
            @{ 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
}
Другие вопросы по тегам