2017/06/26

Asp.Net MVC 다국어

Asp.Net MVC 에서 다국어 설정

사용자 친화적인 라우팅

www.site.com/ko-kr/foo 와 같은 호스트네임 바로 뒤에 언어를 설정 한다.

   1:  public static void RegisterRoutes(RouteCollection routes)
   2:  {
   3:      routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
   4:   
   5:      routes.LowercaseUrls = true;
   6:   
   7:      routes.MapRoute(
   8:          name: "DefaultLocale",
   9:          url: "{locale}/{controller}/{action}/{id}",
  10:          defaults: new
  11:          {
  12:              locale = "ko-kr",
  13:              controller = "Home",
  14:              action = "Index",
  15:              id = UrlParameter.Optional
  16:          });            
  17:  }

필터 설정

필터에서 사용자 응답 쓰레드에 Culture를 설정 하고 locale 입력값이 지원하지 않는 값이면 리디렉션 한다.

   1:  public class FilterConfig
   2:  {
   3:      public static void RegisterGlobalFilters(GlobalFilterCollection filters)
   4:      {
   5:          filters.Add(new HandleErrorAttribute());
   6:   
   7:          filters.Add(new LocalizationAttribute());
   8:      }
   9:   
  10:      public class LocalizationAttribute : ActionFilterAttribute
  11:      {
  12:          public static readonly List<string> Locales = new List<string> { "ko-kr", "en-us" };
  13:          public static readonly string DefaultLocale = "ko-kr";
  14:   
  15:   
  16:          private void SetLocale(string locale)
  17:          {
  18:              Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(locale);
  19:              Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(locale);
  20:          }
  21:   
  22:          public override void OnActionExecuting(ActionExecutingContext filterContext)
  23:          {
  24:              var locale = filterContext.RouteData.Values["locale"] as string;
  25:   
  26:              locale = locale.ToLower();
  27:   
  28:              if (!Locales.Contains(locale))
  29:              {
  30:                  filterContext.RouteData.Values["locale"] = null;
  31:                  filterContext.Result = new RedirectToRouteResult(filterContext.RouteData.Values);
  32:                  return;
  33:              }
  34:   
  35:              this.SetLocale(locale);
  36:          }
  37:      }
  38:  }

리소스 만들기


기본 리소스는 Public 으로 설정해서 View에서 접근 가능하도록 하고 추가 리소스는 '코드 생성 안함' 으로 설정 한다.

모델에 적용

Display Attribute 에 리소스 명과 ResourceType을 설정 한다.
   1:  public class TestModel
   2:  {
   3:      [Display(Name = "TestString", ResourceType = typeof(Messages))]
   4:      public string Name { get; set; }
   5:  }

언어 선택

Dropdown 목록으로 지원되는 언어를 표시 한다.
_SelectLanguage Partial View 작성.
   1:  @{ 
   2:      string currentLocale = TestWebApplication.FilterConfig.LocalizationAttribute.DefaultLocale;
   3:      if (this.ViewContext.RouteData.Values["locale"] != null)
   4:      {
   5:          currentLocale = this.ViewContext.RouteData.Values["locale"].ToString();
   6:      }
   7:   
   8:      var targetPath = string.Format("{0}/{1}{2}",
   9:          ViewContext.RouteData.Values["controller"].ToString(),
  10:          ViewContext.RouteData.Values["action"].ToString(),
  11:          Request.Url.Query);
  12:   
  13:      var targetUrlMask = string.Format("/{{0}}/{0}", targetPath);
  14:  }
  15:   
  16:  <li class="dropdown">
  17:      <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">@currentLocale <span class="caret"></span></a>    
  18:      
  19:      <ul class="dropdown-menu">
  20:          @foreach (var locale in TestWebApplication.FilterConfig.LocalizationAttribute.Locales)
  21:          {
  22:              <li><a href="@string.Format(targetUrlMask, locale)">@locale</a></li>
  23:          }
  24:          
  25:      </ul>
  26:  </li>

레이아웃에 적용
   1:  <div class="navbar navbar-inverse navbar-fixed-top">
   2:      <div class="container">
   3:          <div class="navbar-header">
   4:              <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
   5:                  <span class="icon-bar"></span>
   6:                  <span class="icon-bar"></span>
   7:                  <span class="icon-bar"></span>
   8:              </button>
   9:              @Html.ActionLink("응용 프로그램 이름", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
  10:          </div>
  11:          <div class="navbar-collapse collapse">
  12:              <ul class="nav navbar-nav">
  13:                  <li>@Html.ActionLink("홈", "Index", "Home")</li>
  14:                  <li>@Html.ActionLink("정보", "About", "Home")</li>
  15:                  <li>@Html.ActionLink("연락처", "Contact", "Home")</li>
  16:              </ul>
  17:              <ul class="nav navbar-nav navbar-right">
  18:                  @Html.Partial("_SelectLanguage")
  19:              </ul>
  20:          </div>
  21:      </div>
  22:  </div>

View 테스트

리소스의 문자 출력, 모델에 적용된 리소스 문자 출력 및 현재 시간을 출력.
   1:  @model TestWebApplication.Models.TestModel
   2:   
   3:  <h1>
   4:      @TestWebApplication.Messages.TestString
   5:  </h1>
   6:  <h1>
   7:      @Html.LabelFor(i => i.Name)
   8:  </h1>
   9:  <h1>
  10:      Now: @DateTime.Now
  11:  </h1>

결과 화면


Action 링크에 라우팅이 적용 되었음을 확인 할 수 있다.

댓글 없음:

댓글 쓰기

C# 문자열 포함 여부 확인하기.

ToUpper() 를 사용하면 불필요한 문자열을 생성하므로 좋은 방법은 아니다. string text = "This is an apple." ; string apple = "Apple." ; bool ...