ASP.NET MVC 다국어 대응에 대한 메모

ASP.NET MVC 다국어 대응에 대한 메모

업무로 다국어 대응이 필요한 웹 어플리케이션의 기반 개발을 담당했었는데, 그때 작업한 내용을 정리한 것입니다.

전제 조건

개발

1. 리소스 파일을 준비한다

※리소스 파일의 Access Modifier는 「Public」으로 설정합니다.

※리소스 파일의 격납 장소는 임의로 변경 가능 합니다(ex)Lang > Localize.resx 등)

2. 유저 인증 직후의 처리에 이하의 처리를 추가한다

AuthorizeAttribute Class 를 상속받아 인증 로직을 만들고, 그 내부에 처리를 추가하는 이미지 입니다.

var key = "cultureInfo";
var value = string.Empty;
//cType = DB에서 유저의 컬쳐 정보를 취득
switch (cType)
{
	case 1:
		value = "ja-JP";
		break;
	case 2:
		value = "en-US";
		break;
	default:
		value = "ja-JP";
		break;
}

Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(value);
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(value);

var cookie = new HttpCookie(key);
cookie.Value = value;
Response.Cookies.Add(cookie);

3. Action 실행시마다 컬쳐 설정을 한다

Thread.CurrentThread.CurrentCulture에 설정한 값은 1번의 리퀘스트에서만 유효하므로 설정후엔 Cookie등에 격납해 두고 Action이 발생 되는 타이밍 마다 재설정 해 줄 필요가 있습니다.

InternationalizationAttribute.cs
using System.Globalization;
using System.Threading;
using System.Web;
using System.Web.Mvc;

public class InternationalizationAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var cultureInfo = "ja-JP";
        HttpCookie cookie = filterContext.RequestContext.HttpContext.Request.Cookies["cultureInfo"];
        if (cookie != null && !string.IsNullOrEmpty(cookie.Value))
        {
            cultureInfo = cookie.Value;
        }

        Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(cultureInfo);
        Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(cultureInfo);
    }
}

4. 다국어 하고 싶은 부분에 리소스에 설정한 값을 사용한다

xx.cshtml
<p>@Localize.GettingStartedTitle</p>

<!--  개행 처리 -->
<p>@Html.Raw(Localize.AboutAspNetMvcDesc.Replace("\r\n","<br>"))</p>

<!--  string format사용(에러 메세지 등) [ex)Please enter an amount greater than {0}. ]-->
<p>@string.Format(Localize.ErrorMessage1, "0")</p>

5. 리소스의 키에서 값을 직접 취득할 경우

public string GetResourceValueByName(string name)
{
	var value = string.Empty;
	System.Resources.ResourceManager rm = new System.Resources.ResourceManager("base name", this.GetType().Assembly);
	value = rm.GetString(name).ToString();

	if (!string.IsNullOrEmpty(value))
	{
		return value;
	}
	else
	{
		return name;
	}
}

보통 「Localize.ErrorMessage1」와 같이 값을 설정하는게 제일 좋지만 만약 그게 불가능할 경우, 또는 리소스에서 임의의 키 값으로 밸류 값이 있는지 확인하거나 취득할 경우엔 이런 방법도 있습니다.

필요에 의해선 base name도 인수로 취득한 후, 키 값을 기준으로 값을 취득하는 공통 모듈로 개량하는 것도 바람직 할 듯 합니다.

6. 용도에 따라 리소스 파일을 분리할 경우

분리 방법에 따라 다르지만 개인적으론 이런 느낌으로 나누었습니다.

[Lang]
 ┗ Localize.resx
 ┗ Localize.ja-JP.resx
 ┗ [Contract] // 계약서의 다국어 리소스
   ┗ Localize.resx
   ┗ Localize.ja-JP.resx
 ┗ [Invoice] // 계약서의 다국어 리소스
   ┗ Localize.resx
   ┗ Localize.ja-JP.resx

예시

참고

Pie's Tech Note

생계형 개발자의 메모장

comments powered by Disqus

    rss facebook twitter github youtube mail spotify instagram linkedin google google-plus pinterest medium vimeo stackoverflow reddit quora