재우니의 블로그

 

다국어 사이트는 다음을 번역해야 합니다.

  • 날짜 및 시간 형식 (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/

 

Setup a multilingual site using ASP.NET MVC5

A multilingual site should translate the following: Date and time formatting Currency Text resources: lables, buttons, validation messages, tooltips It must be easy to switch languages. It should b…

blog.chudinov.net

 

샘플 예제

AspMvc5Multilingual-master.zip
0.03MB