ASP.NET MVC5 에서 멀티언어 다국어 multilingual 셋팅하기
다국어 사이트는 다음을 번역해야 합니다.
- 날짜 및 시간 형식 (Date and time formatting)
- 통화 (Currency)
- 텍스트 리소스: 레이블, 버튼, 유효성 검사 메시지, 도구 설명(Text resources: lables, buttons, validation messages, tooltips)
언어 전환이 쉬워야 합니다.
더 많은 언어를 추가하는 것은 상대적으로 쉬워야 합니다.
ASP.NET MVC 5 프로젝트 예제는 https://github.com/mchudinov/AspMvc5Multilingual에서 다운로드할 수 있습니다.
1. Routing
Add lang parameter to routes in RegisterRoutes method of RouteConfig class. Set constraints to enabled languages. Set default language in default route.
한국어와 영어를 사용하기 위해 constraints 를 사용하여 제한을 걸어 en|ko 로 설정했습니다.
- name : 경로의 이름(중복되지 않게만 붙여 주면 됩니다. 그래도 의미 있는 이름을 지어 주는 것이 좋을 것입니다.)
- url : 경로의 형식. {controller}/{action}/{id} 같은 방식으로 계속 적어 왔던 내용입니다.
- defaults : url의 변수들이 기본적으로 어떤 값을 갖느냐에 대한 내용입니다. Controller 이름이라든지, Controller의 함수(Action이라고 불립니다) 이름이 적용됩니다.
- namespaces : 이 route를 사용할 때 어떤 namespace에 있는 것을 찾아야 하는지 알려 줍니다.
- constraints : url의 변수들에 제한을 겁니다.
RouteConfig 클래스의 RegisterRoutes 메서드 에서 경로에 lang 매개변수를 추가 합니다. 사용 가능한 언어로 제약 조건을 설정합니다. 기본 경로에서 기본 언어를 설정합니다.
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Language",
url: "{lang}/{controller}/{action}/{id}",
defaults: new { controller = "Default", action = "Index", id = UrlParameter.Optional },
constraints: new { lang = @"ru|en" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Default", action = "Index", id = UrlParameter.Optional, lang = "en" }
);
}
}
2. Activate culture
Culture 는 컨트롤러의 Initialize 메서드 또는 filter attribute. 을 사용하는 두 가지 방법으로 활성화할 수 있습니다.
2.1 Initialize method
언어 데이터가 필요한 모든 컨트롤러는 Initialize 메서드에서 culture 을 초기화 해야 합니다 . 기본 컨트롤러 클래스를 만들고 그 안에 있는 Initialize 메서드를 재정의해 보겠습니다 .
/// <summary>
/// 생성자가 호출될 때 사용하지 못할 수 있는 데이터를 초기화합니다.
/// 다국어 설정 luckshim
/// </summary>
/// <param name="requestContext">HTTP 컨텍스트 및 경로 데이터입니다.</param>
/// <exception cref="NotSupportedException">Invalid language code '{CurrentLanguageCode}'.</exception>
protected override void Initialize(RequestContext requestContext)
{
if (requestContext.RouteData.Values["lang"] != null && requestContext.RouteData.Values["lang"] as string != "null")
{
CurrentLanguageCode = (string)requestContext.RouteData.Values["lang"];
if (CurrentLanguageCode != null)
{
try
{
Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = new CultureInfo(CurrentLanguageCode);
//NumberFormatInfo nfi = new NumberFormatInfo { CurrencySymbol = "£" };
//Thread.CurrentThread.CurrentUICulture.NumberFormat = Thread.CurrentThread.CurrentCulture.NumberFormat = nfi;
}
catch (Exception)
{
throw new NotSupportedException($"Invalid language code '{CurrentLanguageCode}'.");
}
}
}
base.Initialize(requestContext);
ViewBag.CurrentLanguageCode = CurrentLanguageCode;
}
다른 모든 언어 종속 컨트롤러는 이 기본 컨트롤러 클래스에서 상속되어야 합니다.
2.2 Language localization filter attribute
ActionFilterAttribute 에서 상속된 LocalizationAttribute 클래스를 만듭니다 .
public class LocalizationAttribute : ActionFilterAttribute
{
private readonly string _defaultLanguage;
public LocalizationAttribute(string defaultLanguage)
{
_defaultLanguage = defaultLanguage;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
string lang = (string)filterContext.RouteData.Values["lang"] ?? _defaultLanguage;
if (lang != null)
{
try
{
Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = new CultureInfo(lang);
}
catch (Exception)
{
throw new NotSupportedException($"Invalid language code '{lang}'.");
}
}
}
}
App_Start의 폴더에 FilterConfig의 에 클래스를 추가하고, LocalizationAttribute 을 생성합니다.
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new LocalizationAttribute("en"), 0);
}
}
언어 정보가 필요한 모든 컨트롤러에서 [Localization] 속성을 사용 하십시오.
[Localization("en")]
public class DefaultController : Controller
{
public ActionResult Index()
{
return View();
}
}
3. Create translation resources
3.1 App_LocalResources folder 추가
Asp_Net 폴더 App_LocalResources 를 프로젝트에 추가합니다 . 리소스 파일이 여기에 배치됩니다.
3.2 Add resource files
기본 언어(내 경우 영어)에 대한 언어 리소스 파일 GlobalRes.resx 와 GlobalRes와 같은 다른 언어에 대한 파일을 추가합니다. ru .resx를 App_LocalResources 폴더로 이동합니다. 파일 이름의 두 글자는 RegionInfo.TwoLetterISORegionName Property 에 정의된 대로 지역 정보 ISO(국가 코드) 여야 합니다. 지역 코드의 전체 목록은 Wikipedia 페이지 ISO 3166-1 alpha-2 에서 찾을 수 있습니다 .
3.3 Set resource files properties
- 리소스 유형: 문자열
- 빌드 작업: 포함된 리소스
- 사용자 지정 도구: PublicResXFileCodeGenerator
- 액세스 수정자: 공개
3.4 Add translations for all string resources
3.5 Add reference to resource namespace to Razor in web.config
이 네임스페이스를 표준 ~/Web.config 파일이 아닌 ~/Views/web.config 파일에 추가했는지 확인하십시오 .
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
...
<add namespace="AspMvc5Multilingual.App_LocalResources" />
</namespaces>
</pages>
</system.web.webPages.razor>
모델의 클래스 이름에 대한 번역을 정의하는 DisplayAttribute :
[Display(Name = "Name", ResourceType = typeof(GlobalRes))]
유효성 검사 메시지에 ErrorMessageResourceType 및 ErrorMessageResourceName 을 사용 합니다.
ErrorMessageResourceType = typeof(GlobalRes), ErrorMessageResourceName = "This_field_is_required")
public class Widget
{
[Required(ErrorMessageResourceType = typeof(GlobalRes), ErrorMessageResourceName = "This_field_is_required")]
[StringLength(50, MinimumLength = 5, ErrorMessageResourceType = typeof(GlobalRes), ErrorMessageResourceName = "Must_be_at_least_5_charachters")]
[RegularExpression(@"^[A-Za-z0-9_]+$", ErrorMessageResourceType = typeof(GlobalRes), ErrorMessageResourceName = "Must_contain_only_letters")]
[Display(Name = "Name", ResourceType = typeof(GlobalRes))]
public string Name { get; set; }
}
GlobalRes를 사용하십시오 . Razor 파일에서 참조 이름 변경:
@model AspMvc5Multilingual.Models.Widget
@Html.ActionLink(GlobalRes.MainMenu, "Index", "Default", null, new { title = GlobalRes.Tooltip_help })
<br/>
@GlobalRes.Money: @($"{Model.Money:c0}") <br/>
@GlobalRes.DateAndTime: @Model.DateTime.ToString("F") <br/>
<br/>
@using (Html.BeginForm())
{
@Html.ValidationSummary(false, "")
<div>
@Html.LabelFor(model => model.Name, GlobalRes.Label_text)
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name, "")
</div>
<input type="submit" value="@GlobalRes.Submit_and_test_error_messages" />
}
4. Switch between languages
라우팅을 기반으로 언어 링크를 생성하는 다음 도우미 클래스를 사용합니다. UrlHelper 확장 메소드를 생성 합니다.
public static class LanguageHelper
{
public static MvcHtmlString LangSwitcher(this UrlHelper url, string Name, RouteData routeData, string lang)
{
var liTagBuilder = new TagBuilder("li");
var aTagBuilder = new TagBuilder("a");
var routeValueDictionary = new RouteValueDictionary(routeData.Values);
if (routeValueDictionary.ContainsKey("lang"))
{
if (routeData.Values["lang"] as string == lang)
{
liTagBuilder.AddCssClass("active");
}
else
{
routeValueDictionary["lang"] = lang;
}
}
aTagBuilder.MergeAttribute("href", url.RouteUrl(routeValueDictionary));
aTagBuilder.SetInnerText(Name);
liTagBuilder.InnerHtml = aTagBuilder.ToString();
return new MvcHtmlString(liTagBuilder.ToString());
}
}
예를 들어 _Layout.cshtml 에서 언어 링크 사용
@using AspMvc5Multilingual.Helper
<!DOCTYPE html>
<html>
<head>
...
</head>
<body>
<ul>
@Url.LangSwitcher("English", ViewContext.RouteData, "en")
@Url.LangSwitcher("Russian", ViewContext.RouteData, "ru")
</ul>
<div>
@RenderBody()
</div>
</body>
</html>
5. Format some numbers as another currency then current culture (일부 숫자의 서식을 현재 culture 보다 다른 currency 로 지정)
System.Globalization.NumberFormatInfo 클래스는 숫자 값의 서식 지정 및 구문 분석을 위한 culture-specific 정보를 제공합니다. 사용하기가 매우 쉽습니다.
NumberFormatInfo nfi = new NumberFormatInfo {CurrencySymbol = "€"};
string.Format(nfi,"{0:c0}",12345);
6. 모든 숫자를 다른 통화로 포맷한 다음 현재 문화권으로 지정
NumberFormatInfo nfi = new NumberFormatInfo { CurrencySymbol = "£" };
Thread.CurrentThread.CurrentUICulture.NumberFormat = Thread.CurrentThread.CurrentCulture.NumberFormat =
7. Add new language
- Add new language code in routing map (라우팅 맵에 새 언어 코드 추가)
- Add new resource file and translate all strings in it (새 리소스 파일을 추가하고 그 안의 모든 문자열을 번역합니다.)(
- Add new language switch-link to views (Veiw 에 새 언어 전환 링크 추가)
참고 사이트
https://blog.chudinov.net/setup-a-multilingual-site-using-asp-net-mvc5/
샘플 예제