ASP.NET Core에서 세계화 및 지역화Globalization and localization in ASP.NET Core

작성자: Rick Anderson, Damien Bowden, Bart Calixto, Nadeem AfanaHisham Bin AteyaBy Rick Anderson, Damien Bowden, Bart Calixto, Nadeem Afana, and Hisham Bin Ateya

다국어 웹 사이트를 사용하면 사이트를 더 광범위한 대상에 연결할 수 있습니다.A multilingual website allows the site to reach a wider audience. ASP.NET Core는 다른 언어 및 문화권의 지역화를 위한 서비스 및 미들웨어를 제공합니다.ASP.NET Core provides services and middleware for localizing into different languages and cultures.

국제화는 전역화지역화를 포함합니다.Internationalization involves Globalization and Localization. 세계화는 서로 다른 문화권을 지원하는 앱을 설계하는 프로세스입니다.Globalization is the process of designing apps that support different cultures. 세계화는 특정 지역과 관련이 있는 정의된 언어 스크립트 집합의 입력, 표시 및 출력에 대한 지원을 추가합니다.Globalization adds support for input, display, and output of a defined set of language scripts that relate to specific geographic areas.

지역화는 이미 특정 문화권/로캘로 지역화 가능성을 위해 처리한 세계화된 앱을 조정하는 프로세스입니다.Localization is the process of adapting a globalized app, which you have already processed for localizability, to a particular culture/locale. 자세한 내용은 이 문서의 끝 부분에서 세계화 및 지역화 용어를 참조하세요.For more information see Globalization and localization terms near the end of this document.

앱 지역화 과정은 다음과 같습니다.App localization involves the following:

  1. 앱의 콘텐츠를 지역화 가능하도록 만들기Make the app's content localizable
  2. 지원하는 언어 및 문화권에 대한 지역화된 리소스 제공Provide localized resources for the languages and cultures you support
  3. 각 요청에 대한 언어/문화권을 선택하는 전략 구현Implement a strategy to select the language/culture for each request

예제 코드 살펴보기 및 다운로드 (다운로드 방법)View or download sample code (how to download)

앱의 콘텐츠를 지역화 가능하도록 만들기Make the app's content localizable

IStringLocalizerIStringLocalizer<T>는 지역화된 앱을 개발할 때 생산성을 향상하도록 설계되었습니다.IStringLocalizer and IStringLocalizer<T> were architected to improve productivity when developing localized apps. IStringLocalizerResourceManagerResourceReader를 사용하여 런타임에 문화권 관련 리소스를 제공합니다.IStringLocalizer uses the ResourceManager and ResourceReader to provide culture-specific resources at run time. 인터페이스에는 지역화된 문자열을 반환하기 위한 인덱서 및 IEnumerable이 있습니다.The interface has an indexer and an IEnumerable for returning localized strings. IStringLocalizer는 리소스 파일에 기본 언어 문자열을 저장하도록 요구하지 않습니다.IStringLocalizer doesn't require storing the default language strings in a resource file. 지역화를 대상으로 하는 앱을 개발할 수 있으며 초기 개발에서 리소스 파일을 만들 필요가 없습니다.You can develop an app targeted for localization and not need to create resource files early in development. 아래 코드는 지역화에 대한 "About Title" 문자열을 래핑하는 방법을 보여 줍니다.The code below shows how to wrap the string "About Title" for localization.

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;

namespace Localization.Controllers
{
    [Route("api/[controller]")]
    public class AboutController : Controller
    {
        private readonly IStringLocalizer<AboutController> _localizer;

        public AboutController(IStringLocalizer<AboutController> localizer)
        {
            _localizer = localizer;
        }

        [HttpGet]
        public string Get()
        {
            return _localizer["About Title"];
        }
    }
}

위의 코드에서 IStringLocalizer<T> 구현은 종속성 주입에서 옵니다.In the preceding code, the IStringLocalizer<T> implementation comes from Dependency Injection. "About Title"의 지역화된 값을 찾을 수 없는 경우 인덱서 키가 반환됩니다. 즉, "About Title" 문자열입니다.If the localized value of "About Title" isn't found, then the indexer key is returned, that is, the string "About Title". 앱에서 기본 언어 리터럴 문자열을 그대로 두고 앱 개발에 집중할 수 있도록 로컬라이저에서 래핑할 수 있습니다.You can leave the default language literal strings in the app and wrap them in the localizer, so that you can focus on developing the app. 기본 언어로 앱을 개발하고 먼저 기본 리소스 파일을 만들지 않고 지역화 단계에 대한 준비를 합니다.You develop your app with your default language and prepare it for the localization step without first creating a default resource file. 또는 기존의 접근 방식을 사용하고 기본 언어 문자열을 검색하도록 키를 제공할 수 있습니다.Alternatively, you can use the traditional approach and provide a key to retrieve the default language string. 대부분의 개발자의 경우 기본 언어 .resx 파일을 갖지 않는 새 워크플로와 단순히 문자열 리터럴을 래핑하여 앱을 지역화하는 오버헤드를 줄일 수 있습니다.For many developers the new workflow of not having a default language .resx file and simply wrapping the string literals can reduce the overhead of localizing an app. 다른 개발자는 더 긴 문자열 리터럴과 함께 작동하기 쉽고 지역화된 문자열을 쉽게 업데이트할 수 있으므로 기존의 작업 흐름을 선호합니다.Other developers will prefer the traditional work flow as it can make it easier to work with longer string literals and make it easier to update localized strings.

HTML을 포함하는 리소스에 대해 IHtmlLocalizer<T> 구현을 사용합니다.Use the IHtmlLocalizer<T> implementation for resources that contain HTML. IHtmlLocalizer HTML은 리소스 문자열에 서식이 지정된 인수를 인코딩하지만 리소스 문자열 자체를 HTML 인코딩하지 않습니다.IHtmlLocalizer HTML encodes arguments that are formatted in the resource string, but doesn't HTML encode the resource string itself. 아래 강조 표시된 샘플에서 name 매개 변수의 값만 HTML 인코딩됩니다.In the sample highlighted below, only the value of name parameter is HTML encoded.

using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Localization;

namespace Localization.Controllers
{
    public class BookController : Controller
    {
        private readonly IHtmlLocalizer<BookController> _localizer;

        public BookController(IHtmlLocalizer<BookController> localizer)
        {
            _localizer = localizer;
        }

        public IActionResult Hello(string name)
        {
            ViewData["Message"] = _localizer["<b>Hello</b><i> {0}</i>", name];

            return View();
        }

참고

일반적으로는 HTML이 아닌 텍스트만 지역화합니다.Generally, only localize text, not HTML.

가장 낮은 수준에서 종속성 주입IStringLocalizerFactory를 얻을 수 있습니다.At the lowest level, you can get IStringLocalizerFactory out of Dependency Injection:

{
    public class TestController : Controller
    {
        private readonly IStringLocalizer _localizer;
        private readonly IStringLocalizer _localizer2;

        public TestController(IStringLocalizerFactory factory)
        {
            var type = typeof(SharedResource);
            var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
            _localizer = factory.Create(type);
            _localizer2 = factory.Create("SharedResource", assemblyName.Name);
        }       

        public IActionResult About()
        {
            ViewData["Message"] = _localizer["Your application description page."] 
                + " loc 2: " + _localizer2["Your application description page."];

위의 코드는 두 개의 각 팩터리 만들기 메서드를 보여 줍니다.The code above demonstrates each of the two factory create methods.

컨트롤러, 영역으로 지역화된 문자열을 분할하거나 하나의 컨테이너만을 가질 수 있습니다.You can partition your localized strings by controller, area, or have just one container. 샘플 앱에서 SharedResource라는 더미 클래스는 공유 리소스에 사용됩니다.In the sample app, a dummy class named SharedResource is used for shared resources.

// Dummy class to group shared resources

namespace Localization
{
    public class SharedResource
    {
    }
}

일부 개발자는 Startup 클래스를 사용하여 전역 또는 공유 문자열을 포함합니다.Some developers use the Startup class to contain global or shared strings. 아래 샘플에서 InfoControllerSharedResource 로컬라이저가 사용됩니다.In the sample below, the InfoController and the SharedResource localizers are used:

public class InfoController : Controller
{
    private readonly IStringLocalizer<InfoController> _localizer;
    private readonly IStringLocalizer<SharedResource> _sharedLocalizer;

    public InfoController(IStringLocalizer<InfoController> localizer,
                   IStringLocalizer<SharedResource> sharedLocalizer)
    {
        _localizer = localizer;
        _sharedLocalizer = sharedLocalizer;
    }

    public string TestLoc()
    {
        string msg = "Shared resx: " + _sharedLocalizer["Hello!"] +
                     " Info resx " + _localizer["Hello!"];
        return msg;
    }

지역화 보기View localization

IViewLocalizer 서비스는 보기에 대한 지역화된 문자열을 제공합니다.The IViewLocalizer service provides localized strings for a view. ViewLocalizer 클래스는 이 인터페이스를 구현하고 보기 파일 경로에서 리소스 위치를 찾습니다.The ViewLocalizer class implements this interface and finds the resource location from the view file path. 다음 코드는 IViewLocalizer의 기본 구현을 사용하는 방법을 보여 줍니다.The following code shows how to use the default implementation of IViewLocalizer:

@using Microsoft.AspNetCore.Mvc.Localization

@inject IViewLocalizer Localizer

@{
    ViewData["Title"] = Localizer["About"];
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>

<p>@Localizer["Use this area to provide additional information."]</p>

IViewLocalizer의 기본 구현은 보기의 파일 이름에 따라 리소스 파일을 찾습니다.The default implementation of IViewLocalizer finds the resource file based on the view's file name. 전역 공유 리소스 파일을 사용할 수 있는 옵션이 없습니다.There's no option to use a global shared resource file. ViewLocalizerIHtmlLocalizer를 사용하여 로컬라이저를 구현하므로 Razor는 지역화된 문자열을 HTML 인코딩하지 않습니다.ViewLocalizer implements the localizer using IHtmlLocalizer, so Razor doesn't HTML encode the localized string. 리소스 문자열을 매개 변수화할 수 있으며 IViewLocalizer는 리소스 문자열이 아닌 매개 변수를 HTML 인코딩합니다.You can parameterize resource strings and IViewLocalizer will HTML encode the parameters, but not the resource string. 다음 Razor 태그를 살펴보세요.Consider the following Razor markup:

@Localizer["<i>Hello</i> <b>{0}!</b>", UserManager.GetUserName(User)]

프랑스어 리소스 파일은 다음을 포함할 수 있습니다.A French resource file could contain the following:

KeyKey Value
<i>Hello</i> <b>{0}!</b> <i>Bonjour</i> <b>{0} !</b>

렌더링된 보기는 리소스 파일에서 HTML 표시를 포함합니다.The rendered view would contain the HTML markup from the resource file.

참고

일반적으로는 HTML이 아닌 텍스트만 지역화합니다.Generally, only localize text, not HTML.

보기에서 공유 리소스 파일을 사용하려면 IHtmlLocalizer<T>를 삽입합니다.To use a shared resource file in a view, inject IHtmlLocalizer<T>:

@using Microsoft.AspNetCore.Mvc.Localization
@using Localization.Services

@inject IViewLocalizer Localizer
@inject IHtmlLocalizer<SharedResource> SharedLocalizer

@{
    ViewData["Title"] = Localizer["About"];
}
<h2>@ViewData["Title"].</h2>

<h1>@SharedLocalizer["Hello!"]</h1>

DataAnnotations 지역화DataAnnotations localization

DataAnnotations 오류 메시지는 IStringLocalizer<T>로 지역화됩니다.DataAnnotations error messages are localized with IStringLocalizer<T>. ResourcesPath = "Resources" 옵션을 사용하여 RegisterViewModel의 오류 메시지는 다음 경로 중 하나에 저장될 수 있습니다.Using the option ResourcesPath = "Resources", the error messages in RegisterViewModel can be stored in either of the following paths:

  • Resources/ViewModels.Account.RegisterViewModel.fr.resxResources/ViewModels.Account.RegisterViewModel.fr.resx
  • Resources/ViewModels/Account/RegisterViewModel.fr.resxResources/ViewModels/Account/RegisterViewModel.fr.resx
public class RegisterViewModel
{
    [Required(ErrorMessage = "The Email field is required.")]
    [EmailAddress(ErrorMessage = "The Email field is not a valid email address.")]
    [Display(Name = "Email")]
    public string Email { get; set; }

    [Required(ErrorMessage = "The Password field is required.")]
    [StringLength(8, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }
}

ASP.NET Core MVC 1.1.0 이상에서 비-유효성 검사 특성이 지역화됩니다.In ASP.NET Core MVC 1.1.0 and higher, non-validation attributes are localized. ASP.NET Core MVC 1.0은 비-유효성 검사 특성에 대한 지역화된 문자열을 조회하지 않습니다.ASP.NET Core MVC 1.0 does not look up localized strings for non-validation attributes.

다중 클래스에 대해 하나의 리소스 문자열 사용Using one resource string for multiple classes

다음 코드는 다중 클래스를 사용하여 유효성 검사 특성에 대해 하나의 리소스 문자열을 사용하는 방법을 보여 줍니다.The following code shows how to use one resource string for validation attributes with multiple classes:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
        .AddDataAnnotationsLocalization(options => {
            options.DataAnnotationLocalizerProvider = (type, factory) =>
                factory.Create(typeof(SharedResource));
        });
}

위의 코드에서 SharedResource는 유효성 검사 메시지가 저장되는 resx에 해당하는 클래스입니다.In the preceding code, SharedResource is the class corresponding to the resx where your validation messages are stored. 이 접근 방식으로 DataAnnotations는 각 클래스에 대한 리소스 대신 SharedResource만을 사용합니다.With this approach, DataAnnotations will only use SharedResource, rather than the resource for each class.

지원하는 언어 및 문화권에 대한 지역화된 리소스 제공Provide localized resources for the languages and cultures you support

SupportedCultures 및 SupportedUICulturesSupportedCultures and SupportedUICultures

ASP.NET Core를 사용하면 두 문화권 값 SupportedCulturesSupportedUICultures를 지정할 수 있습니다.ASP.NET Core allows you to specify two culture values, SupportedCultures and SupportedUICultures. SupportedCultures에 대한 CultureInfo 개체는 날짜, 시간, 숫자 및 통화 형식과 같은 문화권 종속 함수의 결과를 결정합니다.The CultureInfo object for SupportedCultures determines the results of culture-dependent functions, such as date, time, number, and currency formatting. SupportedCultures는 또한 텍스트, 대/소문자 규칙 및 문자열 비교의 정렬 순서를 결정합니다.SupportedCultures also determines the sorting order of text, casing conventions, and string comparisons. 서버가 문화권을 가져오는 방법에 대한 자세한 내용은 CultureInfo.CurrentCulture를 참조하세요.See CultureInfo.CurrentCulture for more info on how the server gets the Culture. SupportedUICulturesResourceManager에서 조회하는 번역된 문자열( .resx 파일에서)을 결정합니다.The SupportedUICultures determines which translated strings (from .resx files) are looked up by the ResourceManager. ResourceManagerCurrentUICulture에서 결정되는 문화권별 문자열을 단순히 조회합니다.The ResourceManager simply looks up culture-specific strings that's determined by CurrentUICulture. .NET의 모든 스레드에는 CurrentCultureCurrentUICulture 개체가 있습니다.Every thread in .NET has CurrentCulture and CurrentUICulture objects. ASP.NET Core는 문화권 종속 기능을 렌더링할 때 이러한 값을 검사합니다.ASP.NET Core inspects these values when rendering culture-dependent functions. 예를 들어 현재 스레드의 문화권이 "en-US"(영어, 미국)로 설정되어 있으면 DateTime.Now.ToLongDateString()은 "Thursday, February 18, 2016"을 표시하지만 CurrentCulture가 "es-ES"(스페인어, 스페인)로 설정되어 있으면 출력은 "jueves, 18 de febrero de 2016"이 됩니다.For example, if the current thread's culture is set to "en-US" (English, United States), DateTime.Now.ToLongDateString() displays "Thursday, February 18, 2016", but if CurrentCulture is set to "es-ES" (Spanish, Spain) the output will be "jueves, 18 de febrero de 2016".

리소스 파일Resource files

리소스 파일은 코드에서 지역화 가능한 문자열을 구분하는 데 유용한 메커니즘입니다.A resource file is a useful mechanism for separating localizable strings from code. 기본이 아닌 언어에 대한 번역된 문자열은 .resx 리소스 파일에서 격리됩니다.Translated strings for the non-default language are isolated in .resx resource files. 예를 들어 번역된 문자열을 포함하는 Welcome.es.resx라는 스페인어 리소스 파일을 만들 수 있습니다.For example, you might want to create Spanish resource file named Welcome.es.resx containing translated strings. "es"는 스페인어 언어 코드입니다."es" is the language code for Spanish. Visual Studio에서 이 리소스 파일을 만들려면:To create this resource file in Visual Studio:

  1. 솔루션 탐색기에서 리소스 파일을 포함하는 폴더를 마우스 오른쪽 단추로 클릭하고 추가 > 새 항목을 클릭합니다.In Solution Explorer, right click on the folder which will contain the resource file > Add > New Item.

    중첩된 바로 가기 메뉴: 솔루션 탐색기에서 바로 가기 메뉴가 리소스에 대해 열려 있습니다.

  2. 설치된 템플릿 검색 상자에 "리소스"를 입력하고 파일의 이름을 지정합니다.In the Search installed templates box, enter "resource" and name the file.

    새 항목 추가 대화 상자

  3. 이름 열에 키 값(네이티브 문자열)을 입력하고 열에 번역된 문자열을 입력합니다.Enter the key value (native string) in the Name column and the translated string in the Value column.

    이름 열에 Hello라는 단어가 있고 값 열에 Hola라는 단어(스페인어로 Hello)가 있는 Welcome.es.resx 파일(스페인어에 대한 Welcome 리소스 파일)

    Visual Studio는 Welcome.es.resx 파일을 표시합니다.Visual Studio shows the Welcome.es.resx file.

    Welcome Spanish(es) 리소스 파일을 나타내는 솔루션 탐색기

리소스 파일 이름 지정Resource file naming

리소스의 이름은 해당 클래스의 전체 형식 이름에서 어셈블리 이름을 빼서 지정됩니다.Resources are named for the full type name of their class minus the assembly name. 예를 들어 주 어셈블리가 LocalizationWebsite.Web.Startup 클래스에 대해 LocalizationWebsite.Web.dll인 프로젝트에서 프랑스어 리소스는 Startup.fr.resx로 이름이 지정됩니다.For example, a French resource in a project whose main assembly is LocalizationWebsite.Web.dll for the class LocalizationWebsite.Web.Startup would be named Startup.fr.resx. LocalizationWebsite.Web.Controllers.HomeController 클래스에 대한 리소스는 Controllers.HomeController.fr.resx로 이름이 지정됩니다.A resource for the class LocalizationWebsite.Web.Controllers.HomeController would be named Controllers.HomeController.fr.resx. 대상 클래스의 네임스페이스가 어셈블리 이름과 동일하지 않은 경우 전체 형식 이름이 필요합니다.If your targeted class's namespace isn't the same as the assembly name you will need the full type name. 예를 들어 샘플 프로젝트에서 ExtraNamespace.Tools 형식에 대한 리소스는 ExtraNamespace.Tools.fr.resx로 이름이 지정됩니다.For example, in the sample project a resource for the type ExtraNamespace.Tools would be named ExtraNamespace.Tools.fr.resx.

샘플 프로젝트에서 ConfigureServices 메서드는 ResourcesPath를 "리소스"로 설정하므로 홈 컨트롤러의 프랑스어 리소스 파일에 대한 프로젝트 상대 경로는 Resources/Controllers.HomeController.fr.resx입니다.In the sample project, the ConfigureServices method sets the ResourcesPath to "Resources", so the project relative path for the home controller's French resource file is Resources/Controllers.HomeController.fr.resx. 또는 폴더를 사용하여 리소스 파일을 구성할 수 있습니다.Alternatively, you can use folders to organize resource files. 홈 컨트롤러의 경우 경로는 Resources/Controllers/HomeController.fr.resx입니다.For the home controller, the path would be Resources/Controllers/HomeController.fr.resx. ResourcesPath 옵션을 사용하지 않는 경우 .resx 파일은 프로젝트 기본 디렉터리로 이동합니다.If you don't use the ResourcesPath option, the .resx file would go in the project base directory. HomeController에 대한 리소스 파일은 Controllers.HomeController.fr.resx로 이름이 지정됩니다.The resource file for HomeController would be named Controllers.HomeController.fr.resx. 점 또는 경로 명명 규칙을 사용하도록 선택하는 것은 리소스 파일을 구성하려는 방법에 따라 다릅니다.The choice of using the dot or path naming convention depends on how you want to organize your resource files.

리소스 이름Resource name 점 또는 경로 명명Dot or path naming
Resources/Controllers.HomeController.fr.resxResources/Controllers.HomeController.fr.resx Dot
Resources/Controllers/HomeController.fr.resxResources/Controllers/HomeController.fr.resx 경로Path

Razor 뷰에서 @inject IViewLocalizer를 사용하는 리소스 파일은 유사한 패턴을 따릅니다.Resource files using @inject IViewLocalizer in Razor views follow a similar pattern. 보기에 대한 리소스 파일은 점 이름 지정 또는 경로 이름 지정을 사용하여 이름이 지정될 수 있습니다.The resource file for a view can be named using either dot naming or path naming. Razor 뷰 리소스 파일은 연결된 보기 파일의 경로를 모방합니다.Razor view resource files mimic the path of their associated view file. ResourcesPath를 "리소스"로 설정했다고 가정하면, Views/Home/About.cshtml 보기와 연결된 프랑스어 리소스 파일은 다음 중 하나가 될 수 있습니다.Assuming we set the ResourcesPath to "Resources", the French resource file associated with the Views/Home/About.cshtml view could be either of the following:

  • Resources/Views/Home/About.fr.resxResources/Views/Home/About.fr.resx

  • Resources/Views.Home.About.fr.resxResources/Views.Home.About.fr.resx

ResourcesPath 옵션을 사용하지 않는 경우 보기에 대한 .resx 파일은 보기와 동일한 폴더에 위치합니다.If you don't use the ResourcesPath option, the .resx file for a view would be located in the same folder as the view.

RootNamespaceAttributeRootNamespaceAttribute

RootNamespace 속성은 어셈블리의 루트 네임 스페이스가 어셈블리 이름과 다른 경우 어셈블리의 루트 네임 스페이스를 제공합니다.The RootNamespace attribute provides the root namespace of an assembly when the root namespace of an assembly is different than the assembly name.

경고

이 오류는 프로젝트 이름이 유효한 .NET 식별자가 아닌 경우 발생할 수 있습니다.This can occur when a project's name is not a valid .NET identifier. 예를 들어 my-project-name.csproj가 루트 네임스페이스 my_project_name과 어셈블리 이름 my-project-name을 사용하면 이 오류가 발생합니다.For instance my-project-name.csproj will use the root namespace my_project_name and the assembly name my-project-name leading to this error.

어셈블리의 루트 네임 스페이스가 어셈블리 이름과 다른 경우:If the root namespace of an assembly is different than the assembly name:

  • 지역화는 기본적으로 작동하지 않습니다.Localization does not work by default.
  • 지역화는 리소스가 어셈블리 내에서 검색되는 방식으로 인해 실패합니다.Localization fails due to the way resources are searched for within the assembly. RootNamespace는 실행 중인 프로세스에 사용할 수 없는 빌드 시간 값입니다.RootNamespace is a build-time value which is not available to the executing process.

RootNamespaceAssemblyName과 다른 경우, 다음을 AssemblyInfo.cs에 포함합니다(매개 변수 값을 실제 값으로 대체하여 사용).If the RootNamespace is different from the AssemblyName, include the following in AssemblyInfo.cs (with parameter values replaced with the actual values):

using System.Reflection;
using Microsoft.Extensions.Localization;

[assembly: ResourceLocation("Resource Folder Name")]
[assembly: RootNamespace("App Root Namespace")]

이전 코드를 사용하면 resx 파일을 해결할 수 있습니다.The preceding code enables the successful resolution of resx files.

문화권 대체 동작Culture fallback behavior

리소스를 검색할 때 지역화는 "문화권 대체"에 참여합니다.When searching for a resource, localization engages in "culture fallback". 요청된 문화권에서 시작하여 찾을 수 없으면, 해당 문화권의 부모 문화권으로 되돌아갑니다.Starting from the requested culture, if not found, it reverts to the parent culture of that culture. 그 밖에도 CultureInfo.Parent 속성은 부모 문화권을 나타냅니다.As an aside, the CultureInfo.Parent property represents the parent culture. 이는 일반적으로(항상 그렇지는 않음) ISO에서 국가 기호를 제거합니다.This usually (but not always) means removing the national signifier from the ISO. 예를 들어 멕시코에서 사용되는 스페인어는 "es-MX"입니다.For example, the dialect of Spanish spoken in Mexico is "es-MX". 이 문화권의 부모는 "es"로, 특정 국가에 국한되지 않는 스페인어를 말합니다.It has the parent "es"—Spanish non-specific to any country.

사이트가 문화권 "fr-CA"를 사용하여 "시작" 리소스에 대한 요청을 수신한다고 가정해 보겠습니다.Imagine your site receives a request for a "Welcome" resource using culture "fr-CA". 지역화 시스템은 다음 리소스를 순서대로 찾고, 첫 번째 일치 항목을 선택합니다.The localization system looks for the following resources, in order, and selects the first match:

  • Welcome.fr-CA.resxWelcome.fr-CA.resx
  • Welcome.fr.resxWelcome.fr.resx
  • Welcome.resx(NeutralResourcesLanguage가 "fr-CA"인 경우)Welcome.resx (if the NeutralResourcesLanguage is "fr-CA")

예를 들어 ".fr" 문화권 지정자를 제거하고 프랑스어로 설정된 문화권이 있는 경우 기본 리소스 파일이 읽혀지고 문자열이 지역화됩니다.As an example, if you remove the ".fr" culture designator and you have the culture set to French, the default resource file is read and strings are localized. 리소스 관리자는 요청된 문화권에 맞지 않는 경우에 대한 기본 또는 대체 리소스를 지정합니다.The Resource manager designates a default or fallback resource for when nothing meets your requested culture. 요청된 문화권에 대한 리소스가 없을 때 키를 반환하려는 경우 기본 리소스 파일이 없어야 합니다.If you want to just return the key when missing a resource for the requested culture you must not have a default resource file.

Visual Studio를 사용하여 리소스 파일 생성Generate resource files with Visual Studio

파일 이름에 문화권이 없이(예: Welcome.resx) Visual Studio에서 리소스 파일을 만드는 경우 Visual Studio는 각 문자열에 대한 속성이 있는 C# 클래스를 만듭니다.If you create a resource file in Visual Studio without a culture in the file name (for example, Welcome.resx), Visual Studio will create a C# class with a property for each string. 일반적으로 이는 사용자가 ASP.NET Core에서 원하는 것은 아닙니다.That's usually not what you want with ASP.NET Core. 일반적으로 기본 .resx 리소스 파일(문화권 이름이 없는 .resx 파일)은 없습니다.You typically don't have a default .resx resource file (a .resx file without the culture name). 문화권 이름으로 .resx 파일을 만드는 것이 좋습니다(예: Welcome.fr.resx).We suggest you create the .resx file with a culture name (for example Welcome.fr.resx). 문화권 이름으로 .resx 파일을 만드는 경우 Visual Studio는 클래스 파일을 생성하지 않습니다.When you create a .resx file with a culture name, Visual Studio won't generate the class file.

다른 문화권 추가Add other cultures

각 언어 및 문화권 조합(기본 언어 이외)에는 고유한 리소스 파일이 필요합니다.Each language and culture combination (other than the default language) requires a unique resource file. ISO 언어 코드가 파일 이름의 일부인 새 리소스 파일을 만들어 서로 다른 문화권 및 로캘에 대한 리소스 파일을 만듭니다(예: en-us, fr-caen-gb).You create resource files for different cultures and locales by creating new resource files in which the ISO language codes are part of the file name (for example, en-us, fr-ca, and en-gb). 이러한 ISO 코드는 Welcome.es-MX.resx(스페인어/멕시코)처럼 파일 이름과 .resx 파일 확장명 사이에 위치합니다.These ISO codes are placed between the file name and the .resx file extension, as in Welcome.es-MX.resx (Spanish/Mexico).

각 요청에 대한 언어/문화권을 선택하는 전략 구현Implement a strategy to select the language/culture for each request

지역화 구성Configure localization

지역화는 Startup.ConfigureServices 메서드에서 구성됩니다.Localization is configured in the Startup.ConfigureServices method:

services.AddLocalization(options => options.ResourcesPath = "Resources");

services.AddMvc()
    .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
    .AddDataAnnotationsLocalization();
  • AddLocalization은 서비스 컨테이너에 지역화 서비스를 추가합니다.AddLocalization adds the localization services to the services container. 위의 코드는 또한 "리소스"에 대한 리소스 경로를 설정합니다.The code above also sets the resources path to "Resources".

  • AddViewLocalization은 지역화된 보기 파일에 대한 지원을 추가합니다.AddViewLocalization adds support for localized view files. 이 샘플 보기에서 지역화는 보기 파일 접미사를 기반으로 합니다.In this sample view localization is based on the view file suffix. 예를 들어 Index.fr.cshtml 파일에서 "fr"입니다.For example "fr" in the Index.fr.cshtml file.

  • AddDataAnnotationsLocalizationIStringLocalizer 추상화를 통해 지역화된 DataAnnotations 유효성 검사 메시지에 대한 지원을 추가합니다.AddDataAnnotationsLocalization adds support for localized DataAnnotations validation messages through IStringLocalizer abstractions.

지역화 미들웨어Localization middleware

요청에서 현재 문화권은 지역화 미들웨어에서 설정됩니다.The current culture on a request is set in the localization Middleware. 지역화 미들웨어는 Startup.Configure 메서드에서 활성화됩니다.The localization middleware is enabled in the Startup.Configure method. 지역화 미들웨어는 요청 문화권을 확인할 수 있는 모든 미들웨어 전에 구성되어야 합니다(예: app.UseMvcWithDefaultRoute()).The localization middleware must be configured before any middleware which might check the request culture (for example, app.UseMvcWithDefaultRoute()).

var supportedCultures = new[] { "en-US", "fr" };
var localizationOptions = new RequestLocalizationOptions().SetDefaultCulture(supportedCultures[0])
    .AddSupportedCultures(supportedCultures)
    .AddSupportedUICultures(supportedCultures);

app.UseRequestLocalization(localizationOptions);

app.UseRouting();
app.UseStaticFiles();

app.UseAuthentication();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
});

영어 이외의 언어로 번역된 코드 주석을 보려면 이 GitHub 토론 이슈에서 알려주세요.If you would like to see code comments translated to languages other than English, let us know in this GitHub discussion issue.

UseRequestLocalizationRequestLocalizationOptions 개체를 초기화합니다.UseRequestLocalization initializes a RequestLocalizationOptions object. 모든 요청의 RequestLocalizationOptions에서 RequestCultureProvider의 목록이 열거되고 요청 문화권을 성공적으로 결정할 수 있는 첫 번째 공급자가 사용됩니다.On every request the list of RequestCultureProvider in the RequestLocalizationOptions is enumerated and the first provider that can successfully determine the request culture is used. 기본 공급자는 RequestLocalizationOptions 클래스에서 제공됩니다.The default providers come from the RequestLocalizationOptions class:

  1. QueryStringRequestCultureProvider
  2. CookieRequestCultureProvider
  3. AcceptLanguageHeaderRequestCultureProvider

기본 목록은 가장 구체적인 것에서 덜 구체적으로 것으로 이동합니다.The default list goes from most specific to least specific. 문서의 뒷부분에서 순서를 변경하고 사용자 지정 문화권 공급자를 추가하는 방법을 살펴보겠습니다.Later in the article we'll see how you can change the order and even add a custom culture provider. 공급자가 요청 문화권을 확인할 수 없는 경우 DefaultRequestCulture가 사용됩니다.If none of the providers can determine the request culture, the DefaultRequestCulture is used.

QueryStringRequestCultureProviderQueryStringRequestCultureProvider

일부 앱은 쿼리 문자열을 사용하여 /dotnet/api/system.globalization.cultureinfo?view=netcore-3.1을 설정합니다.Some apps will use a query string to set the /dotnet/api/system.globalization.cultureinfo?view=netcore-3.1. cookie 또는 수용-언어 헤더 방식을 사용하는 앱의 경우 URL에 쿼리 문자열을 추가하는 것은 코드 디버깅 및 테스트에 유용합니다.For apps that use the cookie or Accept-Language header approach, adding a query string to the URL is useful for debugging and testing code. 기본적으로 QueryStringRequestCultureProviderRequestCultureProvider 목록에서 첫 번째 지역화 공급자로 등록됩니다.By default, the QueryStringRequestCultureProvider is registered as the first localization provider in the RequestCultureProvider list. cultureui-culture에 쿼리 문자열 매개 변수를 전달합니다.You pass the query string parameters culture and ui-culture. 다음 예제는 특정 문화권(언어 및 지역)을 스페인어/멕시코로 설정합니다.The following example sets the specific culture (language and region) to Spanish/Mexico:

http://localhost:5000/?culture=es-MX&ui-culture=es-MX

둘 중 하나만을 전달하는 경우(culture 또는 ui-culture) 쿼리 문자열 공급자는 전달한 것을 사용하여 두 값을 설정합니다.If you only pass in one of the two (culture or ui-culture), the query string provider will set both values using the one you passed in. 예를 들어 문화권만을 설정하면 CultureUICulture 모두를 설정합니다.For example, setting just the culture will set both the Culture and the UICulture:

http://localhost:5000/?culture=es-MX

CookieRequestCultureProviderCookieRequestCultureProvider

프로덕션 앱은 종종 메커니즘을 제공하여 ASP.NET Core 문화권 cookie로 문화권을 설정합니다.Production apps will often provide a mechanism to set the culture with the ASP.NET Core culture cookie. MakeCookieValue 메서드를 사용하여 cookie를 만듭니다.Use the MakeCookieValue method to create a cookie.

CookieRequestCultureProvider DefaultCookieName은 사용자의 기본 문화권 정보를 추적하는 데 사용되는 기본 cookie 이름을 반환합니다.The CookieRequestCultureProvider DefaultCookieName returns the default cookie name used to track the user's preferred culture information. 기본 cookie 이름은 .AspNetCore.Culture입니다.The default cookie name is .AspNetCore.Culture.

cookie 형식은 c=%LANGCODE%|uic=%LANGCODE%이며, 여기서 cCulture이고 uicUICulture입니다. 예를 들면 다음과 같습니다.The cookie format is c=%LANGCODE%|uic=%LANGCODE%, where c is Culture and uic is UICulture, for example:

c=en-UK|uic=en-US

문화권 정보 및 UI 문화권 중 하나만 지정하는 경우 지정된 문화권은 문화권 정보 및 UI 문화권 모두에 사용됩니다.If you only specify one of culture info and UI culture, the specified culture will be used for both culture info and UI culture.

수용-언어 HTTP 헤더The Accept-Language HTTP header

수용-언어 헤더는 대부분의 브라우저에서 설정할 수 있으며 원래 사용자의 언어를 지정하도록 계획되었습니다.The Accept-Language header is settable in most browsers and was originally intended to specify the user's language. 이 설정은 브라우저가 전송하도록 설정된 것 또는 기본 운영 체제에서 상속한 것을 나타냅니다.This setting indicates what the browser has been set to send or has inherited from the underlying operating system. 브라우저 요청에서 수용-언어 HTTP 헤더는 사용자의 기본 언어를 검색하는 확실한 방법이 아닙니다(브라우저에서 언어 기본 설정 설정 참조).The Accept-Language HTTP header from a browser request isn't an infallible way to detect the user's preferred language (see Setting language preferences in a browser). 프로덕션 앱은 사용자가 선택한 문화권을 사용자 지정하는 방법을 포함해야 합니다.A production app should include a way for a user to customize their choice of culture.

IE에서 수용-언어 HTTP 헤더 설정Set the Accept-Language HTTP header in IE

  1. 기어 아이콘에서 인터넷 옵션을 누릅니다.From the gear icon, tap Internet Options.

  2. 언어를 누릅니다.Tap Languages.

    인터넷 옵션

  3. 언어 기본 설정 설정을 누릅니다.Tap Set Language Preferences.

  4. 언어 추가를 누릅니다.Tap Add a language.

  5. 언어를 추가합니다.Add the language.

  6. 언어를 누른 다음, 위로 이동을 누릅니다.Tap the language, then tap Move Up.

사용자 지정 공급자 사용Use a custom provider

소비자가 자신의 언어 및 문화권을 데이터베이스에 저장하도록 하기를 원한다고 가정합니다.Suppose you want to let your customers store their language and culture in your databases. 공급자를 작성하여 사용자에 대한 이러한 값을 조회할 수 있습니다.You could write a provider to look up these values for the user. 다음 코드에서는 사용자 지정 공급자를 추가하는 방법을 보여 줍니다.The following code shows how to add a custom provider:

private const string enUSCulture = "en-US";

services.Configure<RequestLocalizationOptions>(options =>
{
    var supportedCultures = new[]
    {
        new CultureInfo(enUSCulture),
        new CultureInfo("fr")
    };

    options.DefaultRequestCulture = new RequestCulture(culture: enUSCulture, uiCulture: enUSCulture);
    options.SupportedCultures = supportedCultures;
    options.SupportedUICultures = supportedCultures;

    options.AddInitialRequestCultureProvider(new CustomRequestCultureProvider(async context =>
    {
        // My custom request culture logic
        return new ProviderCultureResult("en");
    }));
});

RequestLocalizationOptions를 사용하여 지역화 공급자를 추가하거나 제거합니다.Use RequestLocalizationOptions to add or remove localization providers.

프로그래밍 방식으로 문화권 설정Set the culture programmatically

GitHub에서 이 샘플 Localization.StarterWeb 프로젝트는 Culture를 설정하는 UI를 포함합니다.This sample Localization.StarterWeb project on GitHub contains UI to set the Culture. Views/Shared/_SelectLanguagePartial.cshtml 파일을 통해 지원되는 문화권의 목록에서 문화권을 선택할 수 있습니다.The Views/Shared/_SelectLanguagePartial.cshtml file allows you to select the culture from the list of supported cultures:

@using Microsoft.AspNetCore.Builder
@using Microsoft.AspNetCore.Http.Features
@using Microsoft.AspNetCore.Localization
@using Microsoft.AspNetCore.Mvc.Localization
@using Microsoft.Extensions.Options

@inject IViewLocalizer Localizer
@inject IOptions<RequestLocalizationOptions> LocOptions

@{
    var requestCulture = Context.Features.Get<IRequestCultureFeature>();
    var cultureItems = LocOptions.Value.SupportedUICultures
        .Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName })
        .ToList();
    var returnUrl = string.IsNullOrEmpty(Context.Request.Path) ? "~/" : $"~{Context.Request.Path.Value}";
}

<div title="@Localizer["Request culture provider:"] @requestCulture?.Provider?.GetType().Name">
    <form id="selectLanguage" asp-controller="Home" 
          asp-action="SetLanguage" asp-route-returnUrl="@returnUrl" 
          method="post" class="form-horizontal" role="form">
        <label asp-for="@requestCulture.RequestCulture.UICulture.Name">@Localizer["Language:"]</label> <select name="culture"
          onchange="this.form.submit();"
          asp-for="@requestCulture.RequestCulture.UICulture.Name" asp-items="cultureItems">
        </select>
    </form>
</div>

Views/Shared/_SelectLanguagePartial.cshtml 파일은 레이아웃 파일의 footer 섹션에 추가되므로 모든 보기에 사용할 수 있습니다.The Views/Shared/_SelectLanguagePartial.cshtml file is added to the footer section of the layout file so it will be available to all views:

<div class="container body-content" style="margin-top:60px">
    @RenderBody()
    <hr>
    <footer>
        <div class="row">
            <div class="col-md-6">
                <p>&copy; @System.DateTime.Now.Year - Localization</p>
            </div>
            <div class="col-md-6 text-right">
                @await Html.PartialAsync("_SelectLanguagePartial")
            </div>
        </div>
    </footer>
</div>

SetLanguage 메서드는 문화권 cookie를 설정합니다.The SetLanguage method sets the culture cookie.

[HttpPost]
public IActionResult SetLanguage(string culture, string returnUrl)
{
    Response.Cookies.Append(
        CookieRequestCultureProvider.DefaultCookieName,
        CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
        new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) }
    );

    return LocalRedirect(returnUrl);
}

_SelectLanguagePartial.cshtml을 이 프로젝트에 대한 샘플 코드에 플러그 인할 수 없습니다.You can't plug in the _SelectLanguagePartial.cshtml to sample code for this project. GitHubLocalization.StarterWeb 프로젝트에는 종속성 주입 컨테이너를 통해 Razor 부분에 RequestLocalizationOptions를 흐르도록 하는 코드가 있습니다.The Localization.StarterWeb project on GitHub has code to flow the RequestLocalizationOptions to a Razor partial through the Dependency Injection container.

모델 바인딩 경로 데이터 및 쿼리 문자열Model binding route data and query strings

모델 바인딩 경로 데이터 및 쿼리 문자열의 세계화 동작을 참조하세요.See Globalization behavior of model binding route data and query strings.

세계화 및 지역화 용어Globalization and localization terms

또한 앱을 지역화하는 프로세스에는 최신 소프트웨어 개발에 일반적으로 사용되는 관련 문자 집합에 대한 기본적인 이해 및 관련된 문제에 대한 이해가 필요합니다.The process of localizing your app also requires a basic understanding of relevant character sets commonly used in modern software development and an understanding of the issues associated with them. 모든 컴퓨터가 텍스트를 숫자(코드)로 저장하지만 다른 시스템은 다른 숫자를 사용하여 동일한 텍스트를 저장합니다.Although all computers store text as numbers (codes), different systems store the same text using different numbers. 지역화 프로세스는 특정 문화권/로캘에 대한 앱 UI(사용자 인터페이스) 번역을 참조합니다.The localization process refers to translating the app user interface (UI) for a specific culture/locale.

지역화 가능성은 세계화된 앱이 지역화에 대해 준비가 되어 있는지 확인하기 위한 중간 프로세스입니다.Localizability is an intermediate process for verifying that a globalized app is ready for localization.

문화권 이름에 대한 RFC 4646 형식은 <languagecode2>-<country/regioncode2>이며, 여기서 <languagecode2>는 언어 코드이며 <country/regioncode2>는 하위 문화권 코드입니다.The RFC 4646 format for the culture name is <languagecode2>-<country/regioncode2>, where <languagecode2> is the language code and <country/regioncode2> is the subculture code. 예를 들어 스페인어(칠레)의 경우 es-CL, 영어(미국)의 경우 en-US 및 영어(오스트레일리아)의 경우 en-AU입니다.For example, es-CL for Spanish (Chile), en-US for English (United States), and en-AU for English (Australia). RFC 4646은 언어와 관련된 ISO 639 두 문자의 소문자 문화권 코드와 국가 또는 지역과 관련된 ISO 3166 두 문자의 대문자 하위 문화권 코드의 조합입니다.RFC 4646 is a combination of an ISO 639 two-letter lowercase culture code associated with a language and an ISO 3166 two-letter uppercase subculture code associated with a country or region. /previous-versions/commerce-server/ee825488(v=cs.20)을 참조하세요.See /previous-versions/commerce-server/ee825488(v=cs.20).

국제화는 종종 "I18N"으로 단축됩니다.Internationalization is often abbreviated to "I18N". 약어는 첫 번째 및 마지막 문자와 둘 사이의 문자 수를 사용하므로 18은 첫 번째 "I"와 마지막 "N" 사이의 문자 수를 의미합니다.The abbreviation takes the first and last letters and the number of letters between them, so 18 stands for the number of letters between the first "I" and the last "N". 세계화(G11N) 및 지역화(L10N)에도 동일하게 적용됩니다.The same applies to Globalization (G11N), and Localization (L10N).

용어:Terms:

  • 세계화(G11N): 앱이 다른 언어 및 지역을 지원하도록 만드는 프로세스입니다.Globalization (G11N): The process of making an app support different languages and regions.
  • 지역화(L10N): 지정된 언어 및 지역에 대해 앱을 사용자 지정하는 프로세스입니다.Localization (L10N): The process of customizing an app for a given language and region.
  • 국제화(I18N): 세계화와 지역화를 모두 설명합니다.Internationalization (I18N): Describes both globalization and localization.
  • 문화권: 언어이며 경우에 따라 지역입니다.Culture: It's a language and, optionally, a region.
  • 중립 문화권: 지정한 언어가 있지만 지정된 지역이 없는 문화권입니다.Neutral culture: A culture that has a specified language, but not a region. (예: "en", "es")(for example "en", "es")
  • 특정 문화권: 지정된 언어 및 지역이 있는 문화권입니다.Specific culture: A culture that has a specified language and region. (예: "en-US", "en-GB", "es-CL")(for example "en-US", "en-GB", "es-CL")
  • 부모 문화권: 특정 문화권을 포함하는 중립 문화권입니다.Parent culture: The neutral culture that contains a specific culture. (예: "en"은 "en-US" 및 "en-GB"의 부모 문화권)(for example, "en" is the parent culture of "en-US" and "en-GB")
  • 로캘: 로캘은 문화권과 동일합니다.Locale: A locale is the same as a culture.

참고

십진수 필드에는 십진수 쉼표를 입력하지 못할 수도 있습니다.You may not be able to enter decimal commas in decimal fields. 소수점으로 쉼표(“,”)를 사용하는 영어가 아닌 로캘 및 미국 영어가 아닌 날짜 형식에 대해 jQuery 유효성 검사를 지원하려면 앱을 전역화하는 단계를 수행해야 합니다.To support jQuery validation for non-English locales that use a comma (",") for a decimal point, and non US-English date formats, you must take steps to globalize your app. 소수점 추가에 대한 지침은 이 GitHub 문제 4076을 참조하세요.See this GitHub issue 4076 for instructions on adding decimal comma.

참고

ASP.NET Core 3.0 이전에는 요청된 문화권이 지원되지 않는 경우 웹앱이 요청당 LogLevel.Warning 형식의 로그 하나를 작성합니다.Prior to ASP.NET Core 3.0 web apps write one log of type LogLevel.Warning per request if the requested culture is unsupported. 요청당 하나의 LogLevel.Warning을 로깅하면 중복된 정보로 로그 파일이 커질 수 있습니다.Logging one LogLevel.Warning per request is can make large log files with redundant information. 이 동작은 ASP.NET 3.0에서 변경되었습니다.This behavior has been changed in ASP.NET 3.0. RequestLocalizationMiddlewareLogLevel.Debug 형식의 로그를 작성하므로 프로덕션 로그의 크기가 줄어듭니다.The RequestLocalizationMiddleware writes a log of type LogLevel.Debug, which reduces the size of production logs.

추가 자료Additional resources

작성자: Rick Anderson, Damien Bowden, Bart Calixto, Nadeem AfanaHisham Bin AteyaBy Rick Anderson, Damien Bowden, Bart Calixto, Nadeem Afana, and Hisham Bin Ateya

다국어 웹 사이트를 사용하면 사이트를 더 광범위한 대상에 연결할 수 있습니다.A multilingual website allows the site to reach a wider audience. ASP.NET Core는 다른 언어 및 문화권의 지역화를 위한 서비스 및 미들웨어를 제공합니다.ASP.NET Core provides services and middleware for localizing into different languages and cultures.

국제화는 전역화지역화를 포함합니다.Internationalization involves Globalization and Localization. 세계화는 서로 다른 문화권을 지원하는 앱을 설계하는 프로세스입니다.Globalization is the process of designing apps that support different cultures. 세계화는 특정 지역과 관련이 있는 정의된 언어 스크립트 집합의 입력, 표시 및 출력에 대한 지원을 추가합니다.Globalization adds support for input, display, and output of a defined set of language scripts that relate to specific geographic areas.

지역화는 이미 특정 문화권/로캘로 지역화 가능성을 위해 처리한 세계화된 앱을 조정하는 프로세스입니다.Localization is the process of adapting a globalized app, which you have already processed for localizability, to a particular culture/locale. 자세한 내용은 이 문서의 끝 부분에서 세계화 및 지역화 용어를 참조하세요.For more information see Globalization and localization terms near the end of this document.

앱 지역화 과정은 다음과 같습니다.App localization involves the following:

  1. 앱의 콘텐츠를 지역화 가능하도록 만들기Make the app's content localizable
  2. 지원하는 언어 및 문화권에 대한 지역화된 리소스 제공Provide localized resources for the languages and cultures you support
  3. 각 요청에 대한 언어/문화권을 선택하는 전략 구현Implement a strategy to select the language/culture for each request

예제 코드 살펴보기 및 다운로드 (다운로드 방법)View or download sample code (how to download)

앱의 콘텐츠를 지역화 가능하도록 만들기Make the app's content localizable

IStringLocalizerIStringLocalizer<T>는 지역화된 앱을 개발할 때 생산성을 향상하도록 설계되었습니다.IStringLocalizer and IStringLocalizer<T> were architected to improve productivity when developing localized apps. IStringLocalizerResourceManagerResourceReader를 사용하여 런타임에 문화권 관련 리소스를 제공합니다.IStringLocalizer uses the ResourceManager and ResourceReader to provide culture-specific resources at run time. 인터페이스에는 지역화된 문자열을 반환하기 위한 인덱서 및 IEnumerable이 있습니다.The interface has an indexer and an IEnumerable for returning localized strings. IStringLocalizer는 리소스 파일에 기본 언어 문자열을 저장하도록 요구하지 않습니다.IStringLocalizer doesn't require storing the default language strings in a resource file. 지역화를 대상으로 하는 앱을 개발할 수 있으며 초기 개발에서 리소스 파일을 만들 필요가 없습니다.You can develop an app targeted for localization and not need to create resource files early in development. 아래 코드는 지역화에 대한 "About Title" 문자열을 래핑하는 방법을 보여 줍니다.The code below shows how to wrap the string "About Title" for localization.

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;

namespace Localization.Controllers
{
    [Route("api/[controller]")]
    public class AboutController : Controller
    {
        private readonly IStringLocalizer<AboutController> _localizer;

        public AboutController(IStringLocalizer<AboutController> localizer)
        {
            _localizer = localizer;
        }

        [HttpGet]
        public string Get()
        {
            return _localizer["About Title"];
        }
    }
}

위의 코드에서 IStringLocalizer<T> 구현은 종속성 주입에서 옵니다.In the preceding code, the IStringLocalizer<T> implementation comes from Dependency Injection. "About Title"의 지역화된 값을 찾을 수 없는 경우 인덱서 키가 반환됩니다. 즉, "About Title" 문자열입니다.If the localized value of "About Title" isn't found, then the indexer key is returned, that is, the string "About Title". 앱에서 기본 언어 리터럴 문자열을 그대로 두고 앱 개발에 집중할 수 있도록 로컬라이저에서 래핑할 수 있습니다.You can leave the default language literal strings in the app and wrap them in the localizer, so that you can focus on developing the app. 기본 언어로 앱을 개발하고 먼저 기본 리소스 파일을 만들지 않고 지역화 단계에 대한 준비를 합니다.You develop your app with your default language and prepare it for the localization step without first creating a default resource file. 또는 기존의 접근 방식을 사용하고 기본 언어 문자열을 검색하도록 키를 제공할 수 있습니다.Alternatively, you can use the traditional approach and provide a key to retrieve the default language string. 대부분의 개발자의 경우 기본 언어 .resx 파일을 갖지 않는 새 워크플로와 단순히 문자열 리터럴을 래핑하여 앱을 지역화하는 오버헤드를 줄일 수 있습니다.For many developers the new workflow of not having a default language .resx file and simply wrapping the string literals can reduce the overhead of localizing an app. 다른 개발자는 더 긴 문자열 리터럴과 함께 작동하기 쉽고 지역화된 문자열을 쉽게 업데이트할 수 있으므로 기존의 작업 흐름을 선호합니다.Other developers will prefer the traditional work flow as it can make it easier to work with longer string literals and make it easier to update localized strings.

HTML을 포함하는 리소스에 대해 IHtmlLocalizer<T> 구현을 사용합니다.Use the IHtmlLocalizer<T> implementation for resources that contain HTML. IHtmlLocalizer HTML은 리소스 문자열에 서식이 지정된 인수를 인코딩하지만 리소스 문자열 자체를 HTML 인코딩하지 않습니다.IHtmlLocalizer HTML encodes arguments that are formatted in the resource string, but doesn't HTML encode the resource string itself. 아래 강조 표시된 샘플에서 name 매개 변수의 값만 HTML 인코딩됩니다.In the sample highlighted below, only the value of name parameter is HTML encoded.

using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Localization;

namespace Localization.Controllers
{
    public class BookController : Controller
    {
        private readonly IHtmlLocalizer<BookController> _localizer;

        public BookController(IHtmlLocalizer<BookController> localizer)
        {
            _localizer = localizer;
        }

        public IActionResult Hello(string name)
        {
            ViewData["Message"] = _localizer["<b>Hello</b><i> {0}</i>", name];

            return View();
        }

참고

일반적으로는 HTML이 아닌 텍스트만 지역화합니다.Generally, only localize text, not HTML.

가장 낮은 수준에서 종속성 주입IStringLocalizerFactory를 얻을 수 있습니다.At the lowest level, you can get IStringLocalizerFactory out of Dependency Injection:

{
    public class TestController : Controller
    {
        private readonly IStringLocalizer _localizer;
        private readonly IStringLocalizer _localizer2;

        public TestController(IStringLocalizerFactory factory)
        {
            var type = typeof(SharedResource);
            var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
            _localizer = factory.Create(type);
            _localizer2 = factory.Create("SharedResource", assemblyName.Name);
        }       

        public IActionResult About()
        {
            ViewData["Message"] = _localizer["Your application description page."] 
                + " loc 2: " + _localizer2["Your application description page."];

위의 코드는 두 개의 각 팩터리 만들기 메서드를 보여 줍니다.The code above demonstrates each of the two factory create methods.

컨트롤러, 영역으로 지역화된 문자열을 분할하거나 하나의 컨테이너만을 가질 수 있습니다.You can partition your localized strings by controller, area, or have just one container. 샘플 앱에서 SharedResource라는 더미 클래스는 공유 리소스에 사용됩니다.In the sample app, a dummy class named SharedResource is used for shared resources.

// Dummy class to group shared resources

namespace Localization
{
    public class SharedResource
    {
    }
}

일부 개발자는 Startup 클래스를 사용하여 전역 또는 공유 문자열을 포함합니다.Some developers use the Startup class to contain global or shared strings. 아래 샘플에서 InfoControllerSharedResource 로컬라이저가 사용됩니다.In the sample below, the InfoController and the SharedResource localizers are used:

public class InfoController : Controller
{
    private readonly IStringLocalizer<InfoController> _localizer;
    private readonly IStringLocalizer<SharedResource> _sharedLocalizer;

    public InfoController(IStringLocalizer<InfoController> localizer,
                   IStringLocalizer<SharedResource> sharedLocalizer)
    {
        _localizer = localizer;
        _sharedLocalizer = sharedLocalizer;
    }

    public string TestLoc()
    {
        string msg = "Shared resx: " + _sharedLocalizer["Hello!"] +
                     " Info resx " + _localizer["Hello!"];
        return msg;
    }

지역화 보기View localization

IViewLocalizer 서비스는 보기에 대한 지역화된 문자열을 제공합니다.The IViewLocalizer service provides localized strings for a view. ViewLocalizer 클래스는 이 인터페이스를 구현하고 보기 파일 경로에서 리소스 위치를 찾습니다.The ViewLocalizer class implements this interface and finds the resource location from the view file path. 다음 코드는 IViewLocalizer의 기본 구현을 사용하는 방법을 보여 줍니다.The following code shows how to use the default implementation of IViewLocalizer:

@using Microsoft.AspNetCore.Mvc.Localization

@inject IViewLocalizer Localizer

@{
    ViewData["Title"] = Localizer["About"];
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>

<p>@Localizer["Use this area to provide additional information."]</p>

IViewLocalizer의 기본 구현은 보기의 파일 이름에 따라 리소스 파일을 찾습니다.The default implementation of IViewLocalizer finds the resource file based on the view's file name. 전역 공유 리소스 파일을 사용할 수 있는 옵션이 없습니다.There's no option to use a global shared resource file. ViewLocalizerIHtmlLocalizer를 사용하여 로컬라이저를 구현하므로 Razor는 지역화된 문자열을 HTML 인코딩하지 않습니다.ViewLocalizer implements the localizer using IHtmlLocalizer, so Razor doesn't HTML encode the localized string. 리소스 문자열을 매개 변수화할 수 있으며 IViewLocalizer는 리소스 문자열이 아닌 매개 변수를 HTML 인코딩합니다.You can parameterize resource strings and IViewLocalizer will HTML encode the parameters, but not the resource string. 다음 Razor 태그를 살펴보세요.Consider the following Razor markup:

@Localizer["<i>Hello</i> <b>{0}!</b>", UserManager.GetUserName(User)]

프랑스어 리소스 파일은 다음을 포함할 수 있습니다.A French resource file could contain the following:

KeyKey Value
<i>Hello</i> <b>{0}!</b> <i>Bonjour</i> <b>{0} !</b>

렌더링된 보기는 리소스 파일에서 HTML 표시를 포함합니다.The rendered view would contain the HTML markup from the resource file.

참고

일반적으로는 HTML이 아닌 텍스트만 지역화합니다.Generally, only localize text, not HTML.

보기에서 공유 리소스 파일을 사용하려면 IHtmlLocalizer<T>를 삽입합니다.To use a shared resource file in a view, inject IHtmlLocalizer<T>:

@using Microsoft.AspNetCore.Mvc.Localization
@using Localization.Services

@inject IViewLocalizer Localizer
@inject IHtmlLocalizer<SharedResource> SharedLocalizer

@{
    ViewData["Title"] = Localizer["About"];
}
<h2>@ViewData["Title"].</h2>

<h1>@SharedLocalizer["Hello!"]</h1>

DataAnnotations 지역화DataAnnotations localization

DataAnnotations 오류 메시지는 IStringLocalizer<T>로 지역화됩니다.DataAnnotations error messages are localized with IStringLocalizer<T>. ResourcesPath = "Resources" 옵션을 사용하여 RegisterViewModel의 오류 메시지는 다음 경로 중 하나에 저장될 수 있습니다.Using the option ResourcesPath = "Resources", the error messages in RegisterViewModel can be stored in either of the following paths:

  • Resources/ViewModels.Account.RegisterViewModel.fr.resxResources/ViewModels.Account.RegisterViewModel.fr.resx
  • Resources/ViewModels/Account/RegisterViewModel.fr.resxResources/ViewModels/Account/RegisterViewModel.fr.resx
public class RegisterViewModel
{
    [Required(ErrorMessage = "The Email field is required.")]
    [EmailAddress(ErrorMessage = "The Email field is not a valid email address.")]
    [Display(Name = "Email")]
    public string Email { get; set; }

    [Required(ErrorMessage = "The Password field is required.")]
    [StringLength(8, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }
}

ASP.NET Core MVC 1.1.0 이상에서 비-유효성 검사 특성이 지역화됩니다.In ASP.NET Core MVC 1.1.0 and higher, non-validation attributes are localized. ASP.NET Core MVC 1.0은 비-유효성 검사 특성에 대한 지역화된 문자열을 조회하지 않습니다.ASP.NET Core MVC 1.0 does not look up localized strings for non-validation attributes.

다중 클래스에 대해 하나의 리소스 문자열 사용Using one resource string for multiple classes

다음 코드는 다중 클래스를 사용하여 유효성 검사 특성에 대해 하나의 리소스 문자열을 사용하는 방법을 보여 줍니다.The following code shows how to use one resource string for validation attributes with multiple classes:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
        .AddDataAnnotationsLocalization(options => {
            options.DataAnnotationLocalizerProvider = (type, factory) =>
                factory.Create(typeof(SharedResource));
        });
}

위의 코드에서 SharedResource는 유효성 검사 메시지가 저장되는 resx에 해당하는 클래스입니다.In the preceding code, SharedResource is the class corresponding to the resx where your validation messages are stored. 이 접근 방식으로 DataAnnotations는 각 클래스에 대한 리소스 대신 SharedResource만을 사용합니다.With this approach, DataAnnotations will only use SharedResource, rather than the resource for each class.

지원하는 언어 및 문화권에 대한 지역화된 리소스 제공Provide localized resources for the languages and cultures you support

SupportedCultures 및 SupportedUICulturesSupportedCultures and SupportedUICultures

ASP.NET Core를 사용하면 두 문화권 값 SupportedCulturesSupportedUICultures를 지정할 수 있습니다.ASP.NET Core allows you to specify two culture values, SupportedCultures and SupportedUICultures. SupportedCultures에 대한 CultureInfo 개체는 날짜, 시간, 숫자 및 통화 형식과 같은 문화권 종속 함수의 결과를 결정합니다.The CultureInfo object for SupportedCultures determines the results of culture-dependent functions, such as date, time, number, and currency formatting. SupportedCultures는 또한 텍스트, 대/소문자 규칙 및 문자열 비교의 정렬 순서를 결정합니다.SupportedCultures also determines the sorting order of text, casing conventions, and string comparisons. 서버가 문화권을 가져오는 방법에 대한 자세한 내용은 CultureInfo.CurrentCulture를 참조하세요.See CultureInfo.CurrentCulture for more info on how the server gets the Culture. SupportedUICulturesResourceManager에서 조회하는 번역된 문자열( .resx 파일에서)을 결정합니다.The SupportedUICultures determines which translated strings (from .resx files) are looked up by the ResourceManager. ResourceManagerCurrentUICulture에서 결정되는 문화권별 문자열을 단순히 조회합니다.The ResourceManager simply looks up culture-specific strings that's determined by CurrentUICulture. .NET의 모든 스레드에는 CurrentCultureCurrentUICulture 개체가 있습니다.Every thread in .NET has CurrentCulture and CurrentUICulture objects. ASP.NET Core는 문화권 종속 기능을 렌더링할 때 이러한 값을 검사합니다.ASP.NET Core inspects these values when rendering culture-dependent functions. 예를 들어 현재 스레드의 문화권이 "en-US"(영어, 미국)로 설정되어 있으면 DateTime.Now.ToLongDateString()은 "Thursday, February 18, 2016"을 표시하지만 CurrentCulture가 "es-ES"(스페인어, 스페인)로 설정되어 있으면 출력은 "jueves, 18 de febrero de 2016"이 됩니다.For example, if the current thread's culture is set to "en-US" (English, United States), DateTime.Now.ToLongDateString() displays "Thursday, February 18, 2016", but if CurrentCulture is set to "es-ES" (Spanish, Spain) the output will be "jueves, 18 de febrero de 2016".

리소스 파일Resource files

리소스 파일은 코드에서 지역화 가능한 문자열을 구분하는 데 유용한 메커니즘입니다.A resource file is a useful mechanism for separating localizable strings from code. 기본이 아닌 언어에 대한 번역된 문자열은 .resx 리소스 파일에서 격리됩니다.Translated strings for the non-default language are isolated in .resx resource files. 예를 들어 번역된 문자열을 포함하는 Welcome.es.resx라는 스페인어 리소스 파일을 만들 수 있습니다.For example, you might want to create Spanish resource file named Welcome.es.resx containing translated strings. "es"는 스페인어 언어 코드입니다."es" is the language code for Spanish. Visual Studio에서 이 리소스 파일을 만들려면:To create this resource file in Visual Studio:

  1. 솔루션 탐색기에서 리소스 파일을 포함하는 폴더를 마우스 오른쪽 단추로 클릭하고 추가 > 새 항목을 클릭합니다.In Solution Explorer, right click on the folder which will contain the resource file > Add > New Item.

    중첩된 바로 가기 메뉴: 솔루션 탐색기에서 바로 가기 메뉴가 리소스에 대해 열려 있습니다.

  2. 설치된 템플릿 검색 상자에 "리소스"를 입력하고 파일의 이름을 지정합니다.In the Search installed templates box, enter "resource" and name the file.

    새 항목 추가 대화 상자

  3. 이름 열에 키 값(네이티브 문자열)을 입력하고 열에 번역된 문자열을 입력합니다.Enter the key value (native string) in the Name column and the translated string in the Value column.

    이름 열에 Hello라는 단어가 있고 값 열에 Hola라는 단어(스페인어로 Hello)가 있는 Welcome.es.resx 파일(스페인어에 대한 Welcome 리소스 파일)

    Visual Studio는 Welcome.es.resx 파일을 표시합니다.Visual Studio shows the Welcome.es.resx file.

    Welcome Spanish(es) 리소스 파일을 나타내는 솔루션 탐색기

리소스 파일 이름 지정Resource file naming

리소스의 이름은 해당 클래스의 전체 형식 이름에서 어셈블리 이름을 빼서 지정됩니다.Resources are named for the full type name of their class minus the assembly name. 예를 들어 주 어셈블리가 LocalizationWebsite.Web.Startup 클래스에 대해 LocalizationWebsite.Web.dll인 프로젝트에서 프랑스어 리소스는 Startup.fr.resx로 이름이 지정됩니다.For example, a French resource in a project whose main assembly is LocalizationWebsite.Web.dll for the class LocalizationWebsite.Web.Startup would be named Startup.fr.resx. LocalizationWebsite.Web.Controllers.HomeController 클래스에 대한 리소스는 Controllers.HomeController.fr.resx로 이름이 지정됩니다.A resource for the class LocalizationWebsite.Web.Controllers.HomeController would be named Controllers.HomeController.fr.resx. 대상 클래스의 네임스페이스가 어셈블리 이름과 동일하지 않은 경우 전체 형식 이름이 필요합니다.If your targeted class's namespace isn't the same as the assembly name you will need the full type name. 예를 들어 샘플 프로젝트에서 ExtraNamespace.Tools 형식에 대한 리소스는 ExtraNamespace.Tools.fr.resx로 이름이 지정됩니다.For example, in the sample project a resource for the type ExtraNamespace.Tools would be named ExtraNamespace.Tools.fr.resx.

샘플 프로젝트에서 ConfigureServices 메서드는 ResourcesPath를 "리소스"로 설정하므로 홈 컨트롤러의 프랑스어 리소스 파일에 대한 프로젝트 상대 경로는 Resources/Controllers.HomeController.fr.resx입니다.In the sample project, the ConfigureServices method sets the ResourcesPath to "Resources", so the project relative path for the home controller's French resource file is Resources/Controllers.HomeController.fr.resx. 또는 폴더를 사용하여 리소스 파일을 구성할 수 있습니다.Alternatively, you can use folders to organize resource files. 홈 컨트롤러의 경우 경로는 Resources/Controllers/HomeController.fr.resx입니다.For the home controller, the path would be Resources/Controllers/HomeController.fr.resx. ResourcesPath 옵션을 사용하지 않는 경우 .resx 파일은 프로젝트 기본 디렉터리로 이동합니다.If you don't use the ResourcesPath option, the .resx file would go in the project base directory. HomeController에 대한 리소스 파일은 Controllers.HomeController.fr.resx로 이름이 지정됩니다.The resource file for HomeController would be named Controllers.HomeController.fr.resx. 점 또는 경로 명명 규칙을 사용하도록 선택하는 것은 리소스 파일을 구성하려는 방법에 따라 다릅니다.The choice of using the dot or path naming convention depends on how you want to organize your resource files.

리소스 이름Resource name 점 또는 경로 명명Dot or path naming
Resources/Controllers.HomeController.fr.resxResources/Controllers.HomeController.fr.resx Dot
Resources/Controllers/HomeController.fr.resxResources/Controllers/HomeController.fr.resx 경로Path

Razor 뷰에서 @inject IViewLocalizer를 사용하는 리소스 파일은 유사한 패턴을 따릅니다.Resource files using @inject IViewLocalizer in Razor views follow a similar pattern. 보기에 대한 리소스 파일은 점 이름 지정 또는 경로 이름 지정을 사용하여 이름이 지정될 수 있습니다.The resource file for a view can be named using either dot naming or path naming. Razor 뷰 리소스 파일은 연결된 보기 파일의 경로를 모방합니다.Razor view resource files mimic the path of their associated view file. ResourcesPath를 "리소스"로 설정했다고 가정하면, Views/Home/About.cshtml 보기와 연결된 프랑스어 리소스 파일은 다음 중 하나가 될 수 있습니다.Assuming we set the ResourcesPath to "Resources", the French resource file associated with the Views/Home/About.cshtml view could be either of the following:

  • Resources/Views/Home/About.fr.resxResources/Views/Home/About.fr.resx

  • Resources/Views.Home.About.fr.resxResources/Views.Home.About.fr.resx

ResourcesPath 옵션을 사용하지 않는 경우 보기에 대한 .resx 파일은 보기와 동일한 폴더에 위치합니다.If you don't use the ResourcesPath option, the .resx file for a view would be located in the same folder as the view.

RootNamespaceAttributeRootNamespaceAttribute

RootNamespace 속성은 어셈블리의 루트 네임 스페이스가 어셈블리 이름과 다른 경우 어셈블리의 루트 네임 스페이스를 제공합니다.The RootNamespace attribute provides the root namespace of an assembly when the root namespace of an assembly is different than the assembly name.

경고

이 오류는 프로젝트 이름이 유효한 .NET 식별자가 아닌 경우 발생할 수 있습니다.This can occur when a project's name is not a valid .NET identifier. 예를 들어 my-project-name.csproj가 루트 네임스페이스 my_project_name과 어셈블리 이름 my-project-name을 사용하면 이 오류가 발생합니다.For instance my-project-name.csproj will use the root namespace my_project_name and the assembly name my-project-name leading to this error.

어셈블리의 루트 네임 스페이스가 어셈블리 이름과 다른 경우:If the root namespace of an assembly is different than the assembly name:

  • 지역화는 기본적으로 작동하지 않습니다.Localization does not work by default.
  • 지역화는 리소스가 어셈블리 내에서 검색되는 방식으로 인해 실패합니다.Localization fails due to the way resources are searched for within the assembly. RootNamespace는 실행 중인 프로세스에 사용할 수 없는 빌드 시간 값입니다.RootNamespace is a build-time value which is not available to the executing process.

RootNamespaceAssemblyName과 다른 경우, 다음을 AssemblyInfo.cs에 포함합니다(매개 변수 값을 실제 값으로 대체하여 사용).If the RootNamespace is different from the AssemblyName, include the following in AssemblyInfo.cs (with parameter values replaced with the actual values):

using System.Reflection;
using Microsoft.Extensions.Localization;

[assembly: ResourceLocation("Resource Folder Name")]
[assembly: RootNamespace("App Root Namespace")]

이전 코드를 사용하면 resx 파일을 해결할 수 있습니다.The preceding code enables the successful resolution of resx files.

문화권 대체 동작Culture fallback behavior

리소스를 검색할 때 지역화는 "문화권 대체"에 참여합니다.When searching for a resource, localization engages in "culture fallback". 요청된 문화권에서 시작하여 찾을 수 없으면, 해당 문화권의 부모 문화권으로 되돌아갑니다.Starting from the requested culture, if not found, it reverts to the parent culture of that culture. 그 밖에도 CultureInfo.Parent 속성은 부모 문화권을 나타냅니다.As an aside, the CultureInfo.Parent property represents the parent culture. 이는 일반적으로(항상 그렇지는 않음) ISO에서 국가 기호를 제거합니다.This usually (but not always) means removing the national signifier from the ISO. 예를 들어 멕시코에서 사용되는 스페인어는 "es-MX"입니다.For example, the dialect of Spanish spoken in Mexico is "es-MX". 이 문화권의 부모는 "es"로, 특정 국가에 국한되지 않는 스페인어를 말합니다.It has the parent "es"—Spanish non-specific to any country.

사이트가 문화권 "fr-CA"를 사용하여 "시작" 리소스에 대한 요청을 수신한다고 가정해 보겠습니다.Imagine your site receives a request for a "Welcome" resource using culture "fr-CA". 지역화 시스템은 다음 리소스를 순서대로 찾고, 첫 번째 일치 항목을 선택합니다.The localization system looks for the following resources, in order, and selects the first match:

  • Welcome.fr-CA.resxWelcome.fr-CA.resx
  • Welcome.fr.resxWelcome.fr.resx
  • Welcome.resx(NeutralResourcesLanguage가 "fr-CA"인 경우)Welcome.resx (if the NeutralResourcesLanguage is "fr-CA")

예를 들어 ".fr" 문화권 지정자를 제거하고 프랑스어로 설정된 문화권이 있는 경우 기본 리소스 파일이 읽혀지고 문자열이 지역화됩니다.As an example, if you remove the ".fr" culture designator and you have the culture set to French, the default resource file is read and strings are localized. 리소스 관리자는 요청된 문화권에 맞지 않는 경우에 대한 기본 또는 대체 리소스를 지정합니다.The Resource manager designates a default or fallback resource for when nothing meets your requested culture. 요청된 문화권에 대한 리소스가 없을 때 키를 반환하려는 경우 기본 리소스 파일이 없어야 합니다.If you want to just return the key when missing a resource for the requested culture you must not have a default resource file.

Visual Studio를 사용하여 리소스 파일 생성Generate resource files with Visual Studio

파일 이름에 문화권이 없이(예: Welcome.resx) Visual Studio에서 리소스 파일을 만드는 경우 Visual Studio는 각 문자열에 대한 속성이 있는 C# 클래스를 만듭니다.If you create a resource file in Visual Studio without a culture in the file name (for example, Welcome.resx), Visual Studio will create a C# class with a property for each string. 일반적으로 이는 사용자가 ASP.NET Core에서 원하는 것은 아닙니다.That's usually not what you want with ASP.NET Core. 일반적으로 기본 .resx 리소스 파일(문화권 이름이 없는 .resx 파일)은 없습니다.You typically don't have a default .resx resource file (a .resx file without the culture name). 문화권 이름으로 .resx 파일을 만드는 것이 좋습니다(예: Welcome.fr.resx).We suggest you create the .resx file with a culture name (for example Welcome.fr.resx). 문화권 이름으로 .resx 파일을 만드는 경우 Visual Studio는 클래스 파일을 생성하지 않습니다.When you create a .resx file with a culture name, Visual Studio won't generate the class file.

다른 문화권 추가Add other cultures

각 언어 및 문화권 조합(기본 언어 이외)에는 고유한 리소스 파일이 필요합니다.Each language and culture combination (other than the default language) requires a unique resource file. ISO 언어 코드가 파일 이름의 일부인 새 리소스 파일을 만들어 서로 다른 문화권 및 로캘에 대한 리소스 파일을 만듭니다(예: en-us, fr-caen-gb).You create resource files for different cultures and locales by creating new resource files in which the ISO language codes are part of the file name (for example, en-us, fr-ca, and en-gb). 이러한 ISO 코드는 Welcome.es-MX.resx(스페인어/멕시코)처럼 파일 이름과 .resx 파일 확장명 사이에 위치합니다.These ISO codes are placed between the file name and the .resx file extension, as in Welcome.es-MX.resx (Spanish/Mexico).

각 요청에 대한 언어/문화권을 선택하는 전략 구현Implement a strategy to select the language/culture for each request

지역화 구성Configure localization

지역화는 Startup.ConfigureServices 메서드에서 구성됩니다.Localization is configured in the Startup.ConfigureServices method:

services.AddLocalization(options => options.ResourcesPath = "Resources");

services.AddMvc()
    .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
    .AddDataAnnotationsLocalization();
  • AddLocalization은 서비스 컨테이너에 지역화 서비스를 추가합니다.AddLocalization adds the localization services to the services container. 위의 코드는 또한 "리소스"에 대한 리소스 경로를 설정합니다.The code above also sets the resources path to "Resources".

  • AddViewLocalization은 지역화된 보기 파일에 대한 지원을 추가합니다.AddViewLocalization adds support for localized view files. 이 샘플 보기에서 지역화는 보기 파일 접미사를 기반으로 합니다.In this sample view localization is based on the view file suffix. 예를 들어 Index.fr.cshtml 파일에서 "fr"입니다.For example "fr" in the Index.fr.cshtml file.

  • AddDataAnnotationsLocalizationIStringLocalizer 추상화를 통해 지역화된 DataAnnotations 유효성 검사 메시지에 대한 지원을 추가합니다.AddDataAnnotationsLocalization adds support for localized DataAnnotations validation messages through IStringLocalizer abstractions.

지역화 미들웨어Localization middleware

요청에서 현재 문화권은 지역화 미들웨어에서 설정됩니다.The current culture on a request is set in the localization Middleware. 지역화 미들웨어는 Startup.Configure 메서드에서 활성화됩니다.The localization middleware is enabled in the Startup.Configure method. 지역화 미들웨어는 요청 문화권을 확인할 수 있는 모든 미들웨어 전에 구성되어야 합니다(예: app.UseMvcWithDefaultRoute()).The localization middleware must be configured before any middleware which might check the request culture (for example, app.UseMvcWithDefaultRoute()).

var supportedCultures = new[] { "en-US", "fr" };
var localizationOptions = new RequestLocalizationOptions().SetDefaultCulture(supportedCultures[0])
    .AddSupportedCultures(supportedCultures)
    .AddSupportedUICultures(supportedCultures);

app.UseRequestLocalization(localizationOptions);

app.UseRouting();
app.UseStaticFiles();

app.UseAuthentication();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
});

영어 이외의 언어로 번역된 코드 주석을 보려면 이 GitHub 토론 이슈에서 알려주세요.If you would like to see code comments translated to languages other than English, let us know in this GitHub discussion issue.

UseRequestLocalizationRequestLocalizationOptions 개체를 초기화합니다.UseRequestLocalization initializes a RequestLocalizationOptions object. 모든 요청의 RequestLocalizationOptions에서 RequestCultureProvider의 목록이 열거되고 요청 문화권을 성공적으로 결정할 수 있는 첫 번째 공급자가 사용됩니다.On every request the list of RequestCultureProvider in the RequestLocalizationOptions is enumerated and the first provider that can successfully determine the request culture is used. 기본 공급자는 RequestLocalizationOptions 클래스에서 제공됩니다.The default providers come from the RequestLocalizationOptions class:

  1. QueryStringRequestCultureProvider
  2. CookieRequestCultureProvider
  3. AcceptLanguageHeaderRequestCultureProvider

기본 목록은 가장 구체적인 것에서 덜 구체적으로 것으로 이동합니다.The default list goes from most specific to least specific. 문서의 뒷부분에서 순서를 변경하고 사용자 지정 문화권 공급자를 추가하는 방법을 살펴보겠습니다.Later in the article we'll see how you can change the order and even add a custom culture provider. 공급자가 요청 문화권을 확인할 수 없는 경우 DefaultRequestCulture가 사용됩니다.If none of the providers can determine the request culture, the DefaultRequestCulture is used.

QueryStringRequestCultureProviderQueryStringRequestCultureProvider

일부 앱은 쿼리 문자열을 사용하여 /dotnet/api/system.globalization.cultureinfo?view=netcore-3.1을 설정합니다.Some apps will use a query string to set the /dotnet/api/system.globalization.cultureinfo?view=netcore-3.1. cookie 또는 수용-언어 헤더 방식을 사용하는 앱의 경우 URL에 쿼리 문자열을 추가하는 것은 코드 디버깅 및 테스트에 유용합니다.For apps that use the cookie or Accept-Language header approach, adding a query string to the URL is useful for debugging and testing code. 기본적으로 QueryStringRequestCultureProviderRequestCultureProvider 목록에서 첫 번째 지역화 공급자로 등록됩니다.By default, the QueryStringRequestCultureProvider is registered as the first localization provider in the RequestCultureProvider list. cultureui-culture에 쿼리 문자열 매개 변수를 전달합니다.You pass the query string parameters culture and ui-culture. 다음 예제는 특정 문화권(언어 및 지역)을 스페인어/멕시코로 설정합니다.The following example sets the specific culture (language and region) to Spanish/Mexico:

http://localhost:5000/?culture=es-MX&ui-culture=es-MX

둘 중 하나만을 전달하는 경우(culture 또는 ui-culture) 쿼리 문자열 공급자는 전달한 것을 사용하여 두 값을 설정합니다.If you only pass in one of the two (culture or ui-culture), the query string provider will set both values using the one you passed in. 예를 들어 문화권만을 설정하면 CultureUICulture 모두를 설정합니다.For example, setting just the culture will set both the Culture and the UICulture:

http://localhost:5000/?culture=es-MX

CookieRequestCultureProviderCookieRequestCultureProvider

프로덕션 앱은 종종 메커니즘을 제공하여 ASP.NET Core 문화권 cookie로 문화권을 설정합니다.Production apps will often provide a mechanism to set the culture with the ASP.NET Core culture cookie. MakeCookieValue 메서드를 사용하여 cookie를 만듭니다.Use the MakeCookieValue method to create a cookie.

CookieRequestCultureProvider DefaultCookieName은 사용자의 기본 문화권 정보를 추적하는 데 사용되는 기본 cookie 이름을 반환합니다.The CookieRequestCultureProvider DefaultCookieName returns the default cookie name used to track the user's preferred culture information. 기본 cookie 이름은 .AspNetCore.Culture입니다.The default cookie name is .AspNetCore.Culture.

cookie 형식은 c=%LANGCODE%|uic=%LANGCODE%이며, 여기서 cCulture이고 uicUICulture입니다. 예를 들면 다음과 같습니다.The cookie format is c=%LANGCODE%|uic=%LANGCODE%, where c is Culture and uic is UICulture, for example:

c=en-UK|uic=en-US

문화권 정보 및 UI 문화권 중 하나만 지정하는 경우 지정된 문화권은 문화권 정보 및 UI 문화권 모두에 사용됩니다.If you only specify one of culture info and UI culture, the specified culture will be used for both culture info and UI culture.

수용-언어 HTTP 헤더The Accept-Language HTTP header

수용-언어 헤더는 대부분의 브라우저에서 설정할 수 있으며 원래 사용자의 언어를 지정하도록 계획되었습니다.The Accept-Language header is settable in most browsers and was originally intended to specify the user's language. 이 설정은 브라우저가 전송하도록 설정된 것 또는 기본 운영 체제에서 상속한 것을 나타냅니다.This setting indicates what the browser has been set to send or has inherited from the underlying operating system. 브라우저 요청에서 수용-언어 HTTP 헤더는 사용자의 기본 언어를 검색하는 확실한 방법이 아닙니다(브라우저에서 언어 기본 설정 설정 참조).The Accept-Language HTTP header from a browser request isn't an infallible way to detect the user's preferred language (see Setting language preferences in a browser). 프로덕션 앱은 사용자가 선택한 문화권을 사용자 지정하는 방법을 포함해야 합니다.A production app should include a way for a user to customize their choice of culture.

IE에서 수용-언어 HTTP 헤더 설정Set the Accept-Language HTTP header in IE

  1. 기어 아이콘에서 인터넷 옵션을 누릅니다.From the gear icon, tap Internet Options.

  2. 언어를 누릅니다.Tap Languages.

    인터넷 옵션

  3. 언어 기본 설정 설정을 누릅니다.Tap Set Language Preferences.

  4. 언어 추가를 누릅니다.Tap Add a language.

  5. 언어를 추가합니다.Add the language.

  6. 언어를 누른 다음, 위로 이동을 누릅니다.Tap the language, then tap Move Up.

사용자 지정 공급자 사용Use a custom provider

소비자가 자신의 언어 및 문화권을 데이터베이스에 저장하도록 하기를 원한다고 가정합니다.Suppose you want to let your customers store their language and culture in your databases. 공급자를 작성하여 사용자에 대한 이러한 값을 조회할 수 있습니다.You could write a provider to look up these values for the user. 다음 코드에서는 사용자 지정 공급자를 추가하는 방법을 보여 줍니다.The following code shows how to add a custom provider:

private const string enUSCulture = "en-US";

services.Configure<RequestLocalizationOptions>(options =>
{
    var supportedCultures = new[]
    {
        new CultureInfo(enUSCulture),
        new CultureInfo("fr")
    };

    options.DefaultRequestCulture = new RequestCulture(culture: enUSCulture, uiCulture: enUSCulture);
    options.SupportedCultures = supportedCultures;
    options.SupportedUICultures = supportedCultures;

    options.RequestCultureProviders.Insert(0, new CustomRequestCultureProvider(async context =>
    {
        // My custom request culture logic
        return new ProviderCultureResult("en");
    }));
});

RequestLocalizationOptions를 사용하여 지역화 공급자를 추가하거나 제거합니다.Use RequestLocalizationOptions to add or remove localization providers.

프로그래밍 방식으로 문화권 설정Set the culture programmatically

GitHub에서 이 샘플 Localization.StarterWeb 프로젝트는 Culture를 설정하는 UI를 포함합니다.This sample Localization.StarterWeb project on GitHub contains UI to set the Culture. Views/Shared/_SelectLanguagePartial.cshtml 파일을 통해 지원되는 문화권의 목록에서 문화권을 선택할 수 있습니다.The Views/Shared/_SelectLanguagePartial.cshtml file allows you to select the culture from the list of supported cultures:

@using Microsoft.AspNetCore.Builder
@using Microsoft.AspNetCore.Http.Features
@using Microsoft.AspNetCore.Localization
@using Microsoft.AspNetCore.Mvc.Localization
@using Microsoft.Extensions.Options

@inject IViewLocalizer Localizer
@inject IOptions<RequestLocalizationOptions> LocOptions

@{
    var requestCulture = Context.Features.Get<IRequestCultureFeature>();
    var cultureItems = LocOptions.Value.SupportedUICultures
        .Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName })
        .ToList();
    var returnUrl = string.IsNullOrEmpty(Context.Request.Path) ? "~/" : $"~{Context.Request.Path.Value}";
}

<div title="@Localizer["Request culture provider:"] @requestCulture?.Provider?.GetType().Name">
    <form id="selectLanguage" asp-controller="Home" 
          asp-action="SetLanguage" asp-route-returnUrl="@returnUrl" 
          method="post" class="form-horizontal" role="form">
        <label asp-for="@requestCulture.RequestCulture.UICulture.Name">@Localizer["Language:"]</label> <select name="culture"
          onchange="this.form.submit();"
          asp-for="@requestCulture.RequestCulture.UICulture.Name" asp-items="cultureItems">
        </select>
    </form>
</div>

Views/Shared/_SelectLanguagePartial.cshtml 파일은 레이아웃 파일의 footer 섹션에 추가되므로 모든 보기에 사용할 수 있습니다.The Views/Shared/_SelectLanguagePartial.cshtml file is added to the footer section of the layout file so it will be available to all views:

<div class="container body-content" style="margin-top:60px">
    @RenderBody()
    <hr>
    <footer>
        <div class="row">
            <div class="col-md-6">
                <p>&copy; @System.DateTime.Now.Year - Localization</p>
            </div>
            <div class="col-md-6 text-right">
                @await Html.PartialAsync("_SelectLanguagePartial")
            </div>
        </div>
    </footer>
</div>

SetLanguage 메서드는 문화권 cookie를 설정합니다.The SetLanguage method sets the culture cookie.

[HttpPost]
public IActionResult SetLanguage(string culture, string returnUrl)
{
    Response.Cookies.Append(
        CookieRequestCultureProvider.DefaultCookieName,
        CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
        new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) }
    );

    return LocalRedirect(returnUrl);
}

_SelectLanguagePartial.cshtml을 이 프로젝트에 대한 샘플 코드에 플러그 인할 수 없습니다.You can't plug in the _SelectLanguagePartial.cshtml to sample code for this project. GitHubLocalization.StarterWeb 프로젝트에는 종속성 주입 컨테이너를 통해 Razor 부분에 RequestLocalizationOptions를 흐르도록 하는 코드가 있습니다.The Localization.StarterWeb project on GitHub has code to flow the RequestLocalizationOptions to a Razor partial through the Dependency Injection container.

모델 바인딩 경로 데이터 및 쿼리 문자열Model binding route data and query strings

모델 바인딩 경로 데이터 및 쿼리 문자열의 세계화 동작을 참조하세요.See Globalization behavior of model binding route data and query strings.

세계화 및 지역화 용어Globalization and localization terms

또한 앱을 지역화하는 프로세스에는 최신 소프트웨어 개발에 일반적으로 사용되는 관련 문자 집합에 대한 기본적인 이해 및 관련된 문제에 대한 이해가 필요합니다.The process of localizing your app also requires a basic understanding of relevant character sets commonly used in modern software development and an understanding of the issues associated with them. 모든 컴퓨터가 텍스트를 숫자(코드)로 저장하지만 다른 시스템은 다른 숫자를 사용하여 동일한 텍스트를 저장합니다.Although all computers store text as numbers (codes), different systems store the same text using different numbers. 지역화 프로세스는 특정 문화권/로캘에 대한 앱 UI(사용자 인터페이스) 번역을 참조합니다.The localization process refers to translating the app user interface (UI) for a specific culture/locale.

지역화 가능성은 세계화된 앱이 지역화에 대해 준비가 되어 있는지 확인하기 위한 중간 프로세스입니다.Localizability is an intermediate process for verifying that a globalized app is ready for localization.

문화권 이름에 대한 RFC 4646 형식은 <languagecode2>-<country/regioncode2>이며, 여기서 <languagecode2>는 언어 코드이며 <country/regioncode2>는 하위 문화권 코드입니다.The RFC 4646 format for the culture name is <languagecode2>-<country/regioncode2>, where <languagecode2> is the language code and <country/regioncode2> is the subculture code. 예를 들어 스페인어(칠레)의 경우 es-CL, 영어(미국)의 경우 en-US 및 영어(오스트레일리아)의 경우 en-AU입니다.For example, es-CL for Spanish (Chile), en-US for English (United States), and en-AU for English (Australia). RFC 4646은 언어와 관련된 ISO 639 두 문자의 소문자 문화권 코드와 국가 또는 지역과 관련된 ISO 3166 두 문자의 대문자 하위 문화권 코드의 조합입니다.RFC 4646 is a combination of an ISO 639 two-letter lowercase culture code associated with a language and an ISO 3166 two-letter uppercase subculture code associated with a country or region. /previous-versions/commerce-server/ee825488(v=cs.20)을 참조하세요.See /previous-versions/commerce-server/ee825488(v=cs.20).

국제화는 종종 "I18N"으로 단축됩니다.Internationalization is often abbreviated to "I18N". 약어는 첫 번째 및 마지막 문자와 둘 사이의 문자 수를 사용하므로 18은 첫 번째 "I"와 마지막 "N" 사이의 문자 수를 의미합니다.The abbreviation takes the first and last letters and the number of letters between them, so 18 stands for the number of letters between the first "I" and the last "N". 세계화(G11N) 및 지역화(L10N)에도 동일하게 적용됩니다.The same applies to Globalization (G11N), and Localization (L10N).

용어:Terms:

  • 세계화(G11N): 앱이 다른 언어 및 지역을 지원하도록 만드는 프로세스입니다.Globalization (G11N): The process of making an app support different languages and regions.
  • 지역화(L10N): 지정된 언어 및 지역에 대해 앱을 사용자 지정하는 프로세스입니다.Localization (L10N): The process of customizing an app for a given language and region.
  • 국제화(I18N): 세계화와 지역화를 모두 설명합니다.Internationalization (I18N): Describes both globalization and localization.
  • 문화권: 언어이며 경우에 따라 지역입니다.Culture: It's a language and, optionally, a region.
  • 중립 문화권: 지정한 언어가 있지만 지정된 지역이 없는 문화권입니다.Neutral culture: A culture that has a specified language, but not a region. (예: "en", "es")(for example "en", "es")
  • 특정 문화권: 지정된 언어 및 지역이 있는 문화권입니다.Specific culture: A culture that has a specified language and region. (예: "en-US", "en-GB", "es-CL")(for example "en-US", "en-GB", "es-CL")
  • 부모 문화권: 특정 문화권을 포함하는 중립 문화권입니다.Parent culture: The neutral culture that contains a specific culture. (예: "en"은 "en-US" 및 "en-GB"의 부모 문화권)(for example, "en" is the parent culture of "en-US" and "en-GB")
  • 로캘: 로캘은 문화권과 동일합니다.Locale: A locale is the same as a culture.

참고

십진수 필드에는 십진수 쉼표를 입력하지 못할 수도 있습니다.You may not be able to enter decimal commas in decimal fields. 소수점으로 쉼표(“,”)를 사용하는 영어가 아닌 로캘 및 미국 영어가 아닌 날짜 형식에 대해 jQuery 유효성 검사를 지원하려면 앱을 전역화하는 단계를 수행해야 합니다.To support jQuery validation for non-English locales that use a comma (",") for a decimal point, and non US-English date formats, you must take steps to globalize your app. 소수점 추가에 대한 지침은 이 GitHub 문제 4076을 참조하세요.See this GitHub issue 4076 for instructions on adding decimal comma.

추가 자료Additional resources

작성자: Rick Anderson, Damien Bowden, Bart Calixto, Nadeem AfanaHisham Bin AteyaBy Rick Anderson, Damien Bowden, Bart Calixto, Nadeem Afana, and Hisham Bin Ateya

다국어 웹 사이트를 사용하면 사이트를 더 광범위한 대상에 연결할 수 있습니다.A multilingual website allows the site to reach a wider audience. ASP.NET Core는 다른 언어 및 문화권의 지역화를 위한 서비스 및 미들웨어를 제공합니다.ASP.NET Core provides services and middleware for localizing into different languages and cultures.

국제화는 전역화지역화를 포함합니다.Internationalization involves Globalization and Localization. 세계화는 서로 다른 문화권을 지원하는 앱을 설계하는 프로세스입니다.Globalization is the process of designing apps that support different cultures. 세계화는 특정 지역과 관련이 있는 정의된 언어 스크립트 집합의 입력, 표시 및 출력에 대한 지원을 추가합니다.Globalization adds support for input, display, and output of a defined set of language scripts that relate to specific geographic areas.

지역화는 이미 특정 문화권/로캘로 지역화 가능성을 위해 처리한 세계화된 앱을 조정하는 프로세스입니다.Localization is the process of adapting a globalized app, which you have already processed for localizability, to a particular culture/locale. 자세한 내용은 이 문서의 끝 부분에서 세계화 및 지역화 용어를 참조하세요.For more information see Globalization and localization terms near the end of this document.

앱 지역화 과정은 다음과 같습니다.App localization involves the following:

  1. 앱의 콘텐츠를 지역화 가능하도록 만들기Make the app's content localizable
  2. 지원하는 언어 및 문화권에 대한 지역화된 리소스 제공Provide localized resources for the languages and cultures you support
  3. 각 요청에 대한 언어/문화권을 선택하는 전략 구현Implement a strategy to select the language/culture for each request

예제 코드 살펴보기 및 다운로드 (다운로드 방법)View or download sample code (how to download)

앱의 콘텐츠를 지역화 가능하도록 만들기Make the app's content localizable

IStringLocalizerIStringLocalizer<T>는 지역화된 앱을 개발할 때 생산성을 향상하도록 설계되었습니다.IStringLocalizer and IStringLocalizer<T> were architected to improve productivity when developing localized apps. IStringLocalizerResourceManagerResourceReader를 사용하여 런타임에 문화권 관련 리소스를 제공합니다.IStringLocalizer uses the ResourceManager and ResourceReader to provide culture-specific resources at run time. 인터페이스에는 지역화된 문자열을 반환하기 위한 인덱서 및 IEnumerable이 있습니다.The interface has an indexer and an IEnumerable for returning localized strings. IStringLocalizer는 리소스 파일에 기본 언어 문자열을 저장하도록 요구하지 않습니다.IStringLocalizer doesn't require storing the default language strings in a resource file. 지역화를 대상으로 하는 앱을 개발할 수 있으며 초기 개발에서 리소스 파일을 만들 필요가 없습니다.You can develop an app targeted for localization and not need to create resource files early in development. 아래 코드는 지역화에 대한 "About Title" 문자열을 래핑하는 방법을 보여 줍니다.The code below shows how to wrap the string "About Title" for localization.

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;

namespace Localization.Controllers
{
    [Route("api/[controller]")]
    public class AboutController : Controller
    {
        private readonly IStringLocalizer<AboutController> _localizer;

        public AboutController(IStringLocalizer<AboutController> localizer)
        {
            _localizer = localizer;
        }

        [HttpGet]
        public string Get()
        {
            return _localizer["About Title"];
        }
    }
}

위의 코드에서 IStringLocalizer<T> 구현은 종속성 주입에서 옵니다.In the preceding code, the IStringLocalizer<T> implementation comes from Dependency Injection. "About Title"의 지역화된 값을 찾을 수 없는 경우 인덱서 키가 반환됩니다. 즉, "About Title" 문자열입니다.If the localized value of "About Title" isn't found, then the indexer key is returned, that is, the string "About Title". 앱에서 기본 언어 리터럴 문자열을 그대로 두고 앱 개발에 집중할 수 있도록 로컬라이저에서 래핑할 수 있습니다.You can leave the default language literal strings in the app and wrap them in the localizer, so that you can focus on developing the app. 기본 언어로 앱을 개발하고 먼저 기본 리소스 파일을 만들지 않고 지역화 단계에 대한 준비를 합니다.You develop your app with your default language and prepare it for the localization step without first creating a default resource file. 또는 기존의 접근 방식을 사용하고 기본 언어 문자열을 검색하도록 키를 제공할 수 있습니다.Alternatively, you can use the traditional approach and provide a key to retrieve the default language string. 대부분의 개발자의 경우 기본 언어 .resx 파일을 갖지 않는 새 워크플로와 단순히 문자열 리터럴을 래핑하여 앱을 지역화하는 오버헤드를 줄일 수 있습니다.For many developers the new workflow of not having a default language .resx file and simply wrapping the string literals can reduce the overhead of localizing an app. 다른 개발자는 더 긴 문자열 리터럴과 함께 작동하기 쉽고 지역화된 문자열을 쉽게 업데이트할 수 있으므로 기존의 작업 흐름을 선호합니다.Other developers will prefer the traditional work flow as it can make it easier to work with longer string literals and make it easier to update localized strings.

HTML을 포함하는 리소스에 대해 IHtmlLocalizer<T> 구현을 사용합니다.Use the IHtmlLocalizer<T> implementation for resources that contain HTML. IHtmlLocalizer HTML은 리소스 문자열에 서식이 지정된 인수를 인코딩하지만 리소스 문자열 자체를 HTML 인코딩하지 않습니다.IHtmlLocalizer HTML encodes arguments that are formatted in the resource string, but doesn't HTML encode the resource string itself. 아래 강조 표시된 샘플에서 name 매개 변수의 값만 HTML 인코딩됩니다.In the sample highlighted below, only the value of name parameter is HTML encoded.

using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Localization;

namespace Localization.Controllers
{
    public class BookController : Controller
    {
        private readonly IHtmlLocalizer<BookController> _localizer;

        public BookController(IHtmlLocalizer<BookController> localizer)
        {
            _localizer = localizer;
        }

        public IActionResult Hello(string name)
        {
            ViewData["Message"] = _localizer["<b>Hello</b><i> {0}</i>", name];

            return View();
        }

참고

일반적으로는 HTML이 아닌 텍스트만 지역화합니다.Generally, only localize text, not HTML.

가장 낮은 수준에서 종속성 주입IStringLocalizerFactory를 얻을 수 있습니다.At the lowest level, you can get IStringLocalizerFactory out of Dependency Injection:

{
    public class TestController : Controller
    {
        private readonly IStringLocalizer _localizer;
        private readonly IStringLocalizer _localizer2;

        public TestController(IStringLocalizerFactory factory)
        {
            var type = typeof(SharedResource);
            var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
            _localizer = factory.Create(type);
            _localizer2 = factory.Create("SharedResource", assemblyName.Name);
        }       

        public IActionResult About()
        {
            ViewData["Message"] = _localizer["Your application description page."] 
                + " loc 2: " + _localizer2["Your application description page."];

위의 코드는 두 개의 각 팩터리 만들기 메서드를 보여 줍니다.The code above demonstrates each of the two factory create methods.

컨트롤러, 영역으로 지역화된 문자열을 분할하거나 하나의 컨테이너만을 가질 수 있습니다.You can partition your localized strings by controller, area, or have just one container. 샘플 앱에서 SharedResource라는 더미 클래스는 공유 리소스에 사용됩니다.In the sample app, a dummy class named SharedResource is used for shared resources.

// Dummy class to group shared resources

namespace Localization
{
    public class SharedResource
    {
    }
}

일부 개발자는 Startup 클래스를 사용하여 전역 또는 공유 문자열을 포함합니다.Some developers use the Startup class to contain global or shared strings. 아래 샘플에서 InfoControllerSharedResource 로컬라이저가 사용됩니다.In the sample below, the InfoController and the SharedResource localizers are used:

public class InfoController : Controller
{
    private readonly IStringLocalizer<InfoController> _localizer;
    private readonly IStringLocalizer<SharedResource> _sharedLocalizer;

    public InfoController(IStringLocalizer<InfoController> localizer,
                   IStringLocalizer<SharedResource> sharedLocalizer)
    {
        _localizer = localizer;
        _sharedLocalizer = sharedLocalizer;
    }

    public string TestLoc()
    {
        string msg = "Shared resx: " + _sharedLocalizer["Hello!"] +
                     " Info resx " + _localizer["Hello!"];
        return msg;
    }

지역화 보기View localization

IViewLocalizer 서비스는 보기에 대한 지역화된 문자열을 제공합니다.The IViewLocalizer service provides localized strings for a view. ViewLocalizer 클래스는 이 인터페이스를 구현하고 보기 파일 경로에서 리소스 위치를 찾습니다.The ViewLocalizer class implements this interface and finds the resource location from the view file path. 다음 코드는 IViewLocalizer의 기본 구현을 사용하는 방법을 보여 줍니다.The following code shows how to use the default implementation of IViewLocalizer:

@using Microsoft.AspNetCore.Mvc.Localization

@inject IViewLocalizer Localizer

@{
    ViewData["Title"] = Localizer["About"];
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>

<p>@Localizer["Use this area to provide additional information."]</p>

IViewLocalizer의 기본 구현은 보기의 파일 이름에 따라 리소스 파일을 찾습니다.The default implementation of IViewLocalizer finds the resource file based on the view's file name. 전역 공유 리소스 파일을 사용할 수 있는 옵션이 없습니다.There's no option to use a global shared resource file. ViewLocalizerIHtmlLocalizer를 사용하여 로컬라이저를 구현하므로 Razor는 지역화된 문자열을 HTML 인코딩하지 않습니다.ViewLocalizer implements the localizer using IHtmlLocalizer, so Razor doesn't HTML encode the localized string. 리소스 문자열을 매개 변수화할 수 있으며 IViewLocalizer는 리소스 문자열이 아닌 매개 변수를 HTML 인코딩합니다.You can parameterize resource strings and IViewLocalizer will HTML encode the parameters, but not the resource string. 다음 Razor 태그를 살펴보세요.Consider the following Razor markup:

@Localizer["<i>Hello</i> <b>{0}!</b>", UserManager.GetUserName(User)]

프랑스어 리소스 파일은 다음을 포함할 수 있습니다.A French resource file could contain the following:

KeyKey Value
<i>Hello</i> <b>{0}!</b> <i>Bonjour</i> <b>{0} !</b>

렌더링된 보기는 리소스 파일에서 HTML 표시를 포함합니다.The rendered view would contain the HTML markup from the resource file.

참고

일반적으로는 HTML이 아닌 텍스트만 지역화합니다.Generally, only localize text, not HTML.

보기에서 공유 리소스 파일을 사용하려면 IHtmlLocalizer<T>를 삽입합니다.To use a shared resource file in a view, inject IHtmlLocalizer<T>:

@using Microsoft.AspNetCore.Mvc.Localization
@using Localization.Services

@inject IViewLocalizer Localizer
@inject IHtmlLocalizer<SharedResource> SharedLocalizer

@{
    ViewData["Title"] = Localizer["About"];
}
<h2>@ViewData["Title"].</h2>

<h1>@SharedLocalizer["Hello!"]</h1>

DataAnnotations 지역화DataAnnotations localization

DataAnnotations 오류 메시지는 IStringLocalizer<T>로 지역화됩니다.DataAnnotations error messages are localized with IStringLocalizer<T>. ResourcesPath = "Resources" 옵션을 사용하여 RegisterViewModel의 오류 메시지는 다음 경로 중 하나에 저장될 수 있습니다.Using the option ResourcesPath = "Resources", the error messages in RegisterViewModel can be stored in either of the following paths:

  • Resources/ViewModels.Account.RegisterViewModel.fr.resxResources/ViewModels.Account.RegisterViewModel.fr.resx
  • Resources/ViewModels/Account/RegisterViewModel.fr.resxResources/ViewModels/Account/RegisterViewModel.fr.resx
public class RegisterViewModel
{
    [Required(ErrorMessage = "The Email field is required.")]
    [EmailAddress(ErrorMessage = "The Email field is not a valid email address.")]
    [Display(Name = "Email")]
    public string Email { get; set; }

    [Required(ErrorMessage = "The Password field is required.")]
    [StringLength(8, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }
}

ASP.NET Core MVC 1.1.0 이상에서 비-유효성 검사 특성이 지역화됩니다.In ASP.NET Core MVC 1.1.0 and higher, non-validation attributes are localized. ASP.NET Core MVC 1.0은 비-유효성 검사 특성에 대한 지역화된 문자열을 조회하지 않습니다.ASP.NET Core MVC 1.0 does not look up localized strings for non-validation attributes.

다중 클래스에 대해 하나의 리소스 문자열 사용Using one resource string for multiple classes

다음 코드는 다중 클래스를 사용하여 유효성 검사 특성에 대해 하나의 리소스 문자열을 사용하는 방법을 보여 줍니다.The following code shows how to use one resource string for validation attributes with multiple classes:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
        .AddDataAnnotationsLocalization(options => {
            options.DataAnnotationLocalizerProvider = (type, factory) =>
                factory.Create(typeof(SharedResource));
        });
}

위의 코드에서 SharedResource는 유효성 검사 메시지가 저장되는 resx에 해당하는 클래스입니다.In the preceding code, SharedResource is the class corresponding to the resx where your validation messages are stored. 이 접근 방식으로 DataAnnotations는 각 클래스에 대한 리소스 대신 SharedResource만을 사용합니다.With this approach, DataAnnotations will only use SharedResource, rather than the resource for each class.

지원하는 언어 및 문화권에 대한 지역화된 리소스 제공Provide localized resources for the languages and cultures you support

SupportedCultures 및 SupportedUICulturesSupportedCultures and SupportedUICultures

ASP.NET Core를 사용하면 두 문화권 값 SupportedCulturesSupportedUICultures를 지정할 수 있습니다.ASP.NET Core allows you to specify two culture values, SupportedCultures and SupportedUICultures. SupportedCultures에 대한 CultureInfo 개체는 날짜, 시간, 숫자 및 통화 형식과 같은 문화권 종속 함수의 결과를 결정합니다.The CultureInfo object for SupportedCultures determines the results of culture-dependent functions, such as date, time, number, and currency formatting. SupportedCultures는 또한 텍스트, 대/소문자 규칙 및 문자열 비교의 정렬 순서를 결정합니다.SupportedCultures also determines the sorting order of text, casing conventions, and string comparisons. 서버가 문화권을 가져오는 방법에 대한 자세한 내용은 CultureInfo.CurrentCulture를 참조하세요.See CultureInfo.CurrentCulture for more info on how the server gets the Culture. SupportedUICulturesResourceManager에서 조회하는 번역된 문자열( .resx 파일에서)을 결정합니다.The SupportedUICultures determines which translated strings (from .resx files) are looked up by the ResourceManager. ResourceManagerCurrentUICulture에서 결정되는 문화권별 문자열을 단순히 조회합니다.The ResourceManager simply looks up culture-specific strings that's determined by CurrentUICulture. .NET의 모든 스레드에는 CurrentCultureCurrentUICulture 개체가 있습니다.Every thread in .NET has CurrentCulture and CurrentUICulture objects. ASP.NET Core는 문화권 종속 기능을 렌더링할 때 이러한 값을 검사합니다.ASP.NET Core inspects these values when rendering culture-dependent functions. 예를 들어 현재 스레드의 문화권이 "en-US"(영어, 미국)로 설정되어 있으면 DateTime.Now.ToLongDateString()은 "Thursday, February 18, 2016"을 표시하지만 CurrentCulture가 "es-ES"(스페인어, 스페인)로 설정되어 있으면 출력은 "jueves, 18 de febrero de 2016"이 됩니다.For example, if the current thread's culture is set to "en-US" (English, United States), DateTime.Now.ToLongDateString() displays "Thursday, February 18, 2016", but if CurrentCulture is set to "es-ES" (Spanish, Spain) the output will be "jueves, 18 de febrero de 2016".

리소스 파일Resource files

리소스 파일은 코드에서 지역화 가능한 문자열을 구분하는 데 유용한 메커니즘입니다.A resource file is a useful mechanism for separating localizable strings from code. 기본이 아닌 언어에 대한 번역된 문자열은 .resx 리소스 파일에서 격리됩니다.Translated strings for the non-default language are isolated in .resx resource files. 예를 들어 번역된 문자열을 포함하는 Welcome.es.resx라는 스페인어 리소스 파일을 만들 수 있습니다.For example, you might want to create Spanish resource file named Welcome.es.resx containing translated strings. "es"는 스페인어 언어 코드입니다."es" is the language code for Spanish. Visual Studio에서 이 리소스 파일을 만들려면:To create this resource file in Visual Studio:

  1. 솔루션 탐색기에서 리소스 파일을 포함하는 폴더를 마우스 오른쪽 단추로 클릭하고 추가 > 새 항목을 클릭합니다.In Solution Explorer, right click on the folder which will contain the resource file > Add > New Item.

    중첩된 바로 가기 메뉴: 솔루션 탐색기에서 바로 가기 메뉴가 리소스에 대해 열려 있습니다.

  2. 설치된 템플릿 검색 상자에 "리소스"를 입력하고 파일의 이름을 지정합니다.In the Search installed templates box, enter "resource" and name the file.

    새 항목 추가 대화 상자

  3. 이름 열에 키 값(네이티브 문자열)을 입력하고 열에 번역된 문자열을 입력합니다.Enter the key value (native string) in the Name column and the translated string in the Value column.

    이름 열에 Hello라는 단어가 있고 값 열에 Hola라는 단어(스페인어로 Hello)가 있는 Welcome.es.resx 파일(스페인어에 대한 Welcome 리소스 파일)

    Visual Studio는 Welcome.es.resx 파일을 표시합니다.Visual Studio shows the Welcome.es.resx file.

    Welcome Spanish(es) 리소스 파일을 나타내는 솔루션 탐색기

리소스 파일 이름 지정Resource file naming

리소스의 이름은 해당 클래스의 전체 형식 이름에서 어셈블리 이름을 빼서 지정됩니다.Resources are named for the full type name of their class minus the assembly name. 예를 들어 주 어셈블리가 LocalizationWebsite.Web.Startup 클래스에 대해 LocalizationWebsite.Web.dll인 프로젝트에서 프랑스어 리소스는 Startup.fr.resx로 이름이 지정됩니다.For example, a French resource in a project whose main assembly is LocalizationWebsite.Web.dll for the class LocalizationWebsite.Web.Startup would be named Startup.fr.resx. LocalizationWebsite.Web.Controllers.HomeController 클래스에 대한 리소스는 Controllers.HomeController.fr.resx로 이름이 지정됩니다.A resource for the class LocalizationWebsite.Web.Controllers.HomeController would be named Controllers.HomeController.fr.resx. 대상 클래스의 네임스페이스가 어셈블리 이름과 동일하지 않은 경우 전체 형식 이름이 필요합니다.If your targeted class's namespace isn't the same as the assembly name you will need the full type name. 예를 들어 샘플 프로젝트에서 ExtraNamespace.Tools 형식에 대한 리소스는 ExtraNamespace.Tools.fr.resx로 이름이 지정됩니다.For example, in the sample project a resource for the type ExtraNamespace.Tools would be named ExtraNamespace.Tools.fr.resx.

샘플 프로젝트에서 ConfigureServices 메서드는 ResourcesPath를 "리소스"로 설정하므로 홈 컨트롤러의 프랑스어 리소스 파일에 대한 프로젝트 상대 경로는 Resources/Controllers.HomeController.fr.resx입니다.In the sample project, the ConfigureServices method sets the ResourcesPath to "Resources", so the project relative path for the home controller's French resource file is Resources/Controllers.HomeController.fr.resx. 또는 폴더를 사용하여 리소스 파일을 구성할 수 있습니다.Alternatively, you can use folders to organize resource files. 홈 컨트롤러의 경우 경로는 Resources/Controllers/HomeController.fr.resx입니다.For the home controller, the path would be Resources/Controllers/HomeController.fr.resx. ResourcesPath 옵션을 사용하지 않는 경우 .resx 파일은 프로젝트 기본 디렉터리로 이동합니다.If you don't use the ResourcesPath option, the .resx file would go in the project base directory. HomeController에 대한 리소스 파일은 Controllers.HomeController.fr.resx로 이름이 지정됩니다.The resource file for HomeController would be named Controllers.HomeController.fr.resx. 점 또는 경로 명명 규칙을 사용하도록 선택하는 것은 리소스 파일을 구성하려는 방법에 따라 다릅니다.The choice of using the dot or path naming convention depends on how you want to organize your resource files.

리소스 이름Resource name 점 또는 경로 명명Dot or path naming
Resources/Controllers.HomeController.fr.resxResources/Controllers.HomeController.fr.resx Dot
Resources/Controllers/HomeController.fr.resxResources/Controllers/HomeController.fr.resx 경로Path

Razor 뷰에서 @inject IViewLocalizer를 사용하는 리소스 파일은 유사한 패턴을 따릅니다.Resource files using @inject IViewLocalizer in Razor views follow a similar pattern. 보기에 대한 리소스 파일은 점 이름 지정 또는 경로 이름 지정을 사용하여 이름이 지정될 수 있습니다.The resource file for a view can be named using either dot naming or path naming. Razor 뷰 리소스 파일은 연결된 보기 파일의 경로를 모방합니다.Razor view resource files mimic the path of their associated view file. ResourcesPath를 "리소스"로 설정했다고 가정하면, Views/Home/About.cshtml 보기와 연결된 프랑스어 리소스 파일은 다음 중 하나가 될 수 있습니다.Assuming we set the ResourcesPath to "Resources", the French resource file associated with the Views/Home/About.cshtml view could be either of the following:

  • Resources/Views/Home/About.fr.resxResources/Views/Home/About.fr.resx

  • Resources/Views.Home.About.fr.resxResources/Views.Home.About.fr.resx

ResourcesPath 옵션을 사용하지 않는 경우 보기에 대한 .resx 파일은 보기와 동일한 폴더에 위치합니다.If you don't use the ResourcesPath option, the .resx file for a view would be located in the same folder as the view.

RootNamespaceAttributeRootNamespaceAttribute

RootNamespace 속성은 어셈블리의 루트 네임 스페이스가 어셈블리 이름과 다른 경우 어셈블리의 루트 네임 스페이스를 제공합니다.The RootNamespace attribute provides the root namespace of an assembly when the root namespace of an assembly is different than the assembly name.

경고

이 오류는 프로젝트 이름이 유효한 .NET 식별자가 아닌 경우 발생할 수 있습니다.This can occur when a project's name is not a valid .NET identifier. 예를 들어 my-project-name.csproj가 루트 네임스페이스 my_project_name과 어셈블리 이름 my-project-name을 사용하면 이 오류가 발생합니다.For instance my-project-name.csproj will use the root namespace my_project_name and the assembly name my-project-name leading to this error.

어셈블리의 루트 네임 스페이스가 어셈블리 이름과 다른 경우:If the root namespace of an assembly is different than the assembly name:

  • 지역화는 기본적으로 작동하지 않습니다.Localization does not work by default.
  • 지역화는 리소스가 어셈블리 내에서 검색되는 방식으로 인해 실패합니다.Localization fails due to the way resources are searched for within the assembly. RootNamespace는 실행 중인 프로세스에 사용할 수 없는 빌드 시간 값입니다.RootNamespace is a build-time value which is not available to the executing process.

RootNamespaceAssemblyName과 다른 경우, 다음을 AssemblyInfo.cs에 포함합니다(매개 변수 값을 실제 값으로 대체하여 사용).If the RootNamespace is different from the AssemblyName, include the following in AssemblyInfo.cs (with parameter values replaced with the actual values):

using System.Reflection;
using Microsoft.Extensions.Localization;

[assembly: ResourceLocation("Resource Folder Name")]
[assembly: RootNamespace("App Root Namespace")]

이전 코드를 사용하면 resx 파일을 해결할 수 있습니다.The preceding code enables the successful resolution of resx files.

문화권 대체 동작Culture fallback behavior

리소스를 검색할 때 지역화는 "문화권 대체"에 참여합니다.When searching for a resource, localization engages in "culture fallback". 요청된 문화권에서 시작하여 찾을 수 없으면, 해당 문화권의 부모 문화권으로 되돌아갑니다.Starting from the requested culture, if not found, it reverts to the parent culture of that culture. 그 밖에도 CultureInfo.Parent 속성은 부모 문화권을 나타냅니다.As an aside, the CultureInfo.Parent property represents the parent culture. 이는 일반적으로(항상 그렇지는 않음) ISO에서 국가 기호를 제거합니다.This usually (but not always) means removing the national signifier from the ISO. 예를 들어 멕시코에서 사용되는 스페인어는 "es-MX"입니다.For example, the dialect of Spanish spoken in Mexico is "es-MX". 이 문화권의 부모는 "es"로, 특정 국가에 국한되지 않는 스페인어를 말합니다.It has the parent "es"—Spanish non-specific to any country.

사이트가 문화권 "fr-CA"를 사용하여 "시작" 리소스에 대한 요청을 수신한다고 가정해 보겠습니다.Imagine your site receives a request for a "Welcome" resource using culture "fr-CA". 지역화 시스템은 다음 리소스를 순서대로 찾고, 첫 번째 일치 항목을 선택합니다.The localization system looks for the following resources, in order, and selects the first match:

  • Welcome.fr-CA.resxWelcome.fr-CA.resx
  • Welcome.fr.resxWelcome.fr.resx
  • Welcome.resx(NeutralResourcesLanguage가 "fr-CA"인 경우)Welcome.resx (if the NeutralResourcesLanguage is "fr-CA")

예를 들어 ".fr" 문화권 지정자를 제거하고 프랑스어로 설정된 문화권이 있는 경우 기본 리소스 파일이 읽혀지고 문자열이 지역화됩니다.As an example, if you remove the ".fr" culture designator and you have the culture set to French, the default resource file is read and strings are localized. 리소스 관리자는 요청된 문화권에 맞지 않는 경우에 대한 기본 또는 대체 리소스를 지정합니다.The Resource manager designates a default or fallback resource for when nothing meets your requested culture. 요청된 문화권에 대한 리소스가 없을 때 키를 반환하려는 경우 기본 리소스 파일이 없어야 합니다.If you want to just return the key when missing a resource for the requested culture you must not have a default resource file.

Visual Studio를 사용하여 리소스 파일 생성Generate resource files with Visual Studio

파일 이름에 문화권이 없이(예: Welcome.resx) Visual Studio에서 리소스 파일을 만드는 경우 Visual Studio는 각 문자열에 대한 속성이 있는 C# 클래스를 만듭니다.If you create a resource file in Visual Studio without a culture in the file name (for example, Welcome.resx), Visual Studio will create a C# class with a property for each string. 일반적으로 이는 사용자가 ASP.NET Core에서 원하는 것은 아닙니다.That's usually not what you want with ASP.NET Core. 일반적으로 기본 .resx 리소스 파일(문화권 이름이 없는 .resx 파일)은 없습니다.You typically don't have a default .resx resource file (a .resx file without the culture name). 문화권 이름으로 .resx 파일을 만드는 것이 좋습니다(예: Welcome.fr.resx).We suggest you create the .resx file with a culture name (for example Welcome.fr.resx). 문화권 이름으로 .resx 파일을 만드는 경우 Visual Studio는 클래스 파일을 생성하지 않습니다.When you create a .resx file with a culture name, Visual Studio won't generate the class file.

다른 문화권 추가Add other cultures

각 언어 및 문화권 조합(기본 언어 이외)에는 고유한 리소스 파일이 필요합니다.Each language and culture combination (other than the default language) requires a unique resource file. ISO 언어 코드가 파일 이름의 일부인 새 리소스 파일을 만들어 서로 다른 문화권 및 로캘에 대한 리소스 파일을 만듭니다(예: en-us, fr-caen-gb).You create resource files for different cultures and locales by creating new resource files in which the ISO language codes are part of the file name (for example, en-us, fr-ca, and en-gb). 이러한 ISO 코드는 Welcome.es-MX.resx(스페인어/멕시코)처럼 파일 이름과 .resx 파일 확장명 사이에 위치합니다.These ISO codes are placed between the file name and the .resx file extension, as in Welcome.es-MX.resx (Spanish/Mexico).

각 요청에 대한 언어/문화권을 선택하는 전략 구현Implement a strategy to select the language/culture for each request

지역화 구성Configure localization

지역화는 Startup.ConfigureServices 메서드에서 구성됩니다.Localization is configured in the Startup.ConfigureServices method:

services.AddLocalization(options => options.ResourcesPath = "Resources");

services.AddMvc()
    .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
    .AddDataAnnotationsLocalization();
  • AddLocalization은 서비스 컨테이너에 지역화 서비스를 추가합니다.AddLocalization adds the localization services to the services container. 위의 코드는 또한 "리소스"에 대한 리소스 경로를 설정합니다.The code above also sets the resources path to "Resources".

  • AddViewLocalization은 지역화된 보기 파일에 대한 지원을 추가합니다.AddViewLocalization adds support for localized view files. 이 샘플 보기에서 지역화는 보기 파일 접미사를 기반으로 합니다.In this sample view localization is based on the view file suffix. 예를 들어 Index.fr.cshtml 파일에서 "fr"입니다.For example "fr" in the Index.fr.cshtml file.

  • AddDataAnnotationsLocalizationIStringLocalizer 추상화를 통해 지역화된 DataAnnotations 유효성 검사 메시지에 대한 지원을 추가합니다.AddDataAnnotationsLocalization adds support for localized DataAnnotations validation messages through IStringLocalizer abstractions.

지역화 미들웨어Localization middleware

요청에서 현재 문화권은 지역화 미들웨어에서 설정됩니다.The current culture on a request is set in the localization Middleware. 지역화 미들웨어는 Startup.Configure 메서드에서 활성화됩니다.The localization middleware is enabled in the Startup.Configure method. 지역화 미들웨어는 요청 문화권을 확인할 수 있는 모든 미들웨어 전에 구성되어야 합니다(예: app.UseMvcWithDefaultRoute()).The localization middleware must be configured before any middleware which might check the request culture (for example, app.UseMvcWithDefaultRoute()).

var supportedCultures = new[] { "en-US", "fr" };
var localizationOptions = new RequestLocalizationOptions().SetDefaultCulture(supportedCultures[0])
    .AddSupportedCultures(supportedCultures)
    .AddSupportedUICultures(supportedCultures);

app.UseRequestLocalization(localizationOptions);

app.UseRouting();
app.UseStaticFiles();

app.UseAuthentication();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
});

영어 이외의 언어로 번역된 코드 주석을 보려면 이 GitHub 토론 이슈에서 알려주세요.If you would like to see code comments translated to languages other than English, let us know in this GitHub discussion issue.

UseRequestLocalizationRequestLocalizationOptions 개체를 초기화합니다.UseRequestLocalization initializes a RequestLocalizationOptions object. 모든 요청의 RequestLocalizationOptions에서 RequestCultureProvider의 목록이 열거되고 요청 문화권을 성공적으로 결정할 수 있는 첫 번째 공급자가 사용됩니다.On every request the list of RequestCultureProvider in the RequestLocalizationOptions is enumerated and the first provider that can successfully determine the request culture is used. 기본 공급자는 RequestLocalizationOptions 클래스에서 제공됩니다.The default providers come from the RequestLocalizationOptions class:

  1. QueryStringRequestCultureProvider
  2. CookieRequestCultureProvider
  3. AcceptLanguageHeaderRequestCultureProvider

기본 목록은 가장 구체적인 것에서 덜 구체적으로 것으로 이동합니다.The default list goes from most specific to least specific. 문서의 뒷부분에서 순서를 변경하고 사용자 지정 문화권 공급자를 추가하는 방법을 살펴보겠습니다.Later in the article we'll see how you can change the order and even add a custom culture provider. 공급자가 요청 문화권을 확인할 수 없는 경우 DefaultRequestCulture가 사용됩니다.If none of the providers can determine the request culture, the DefaultRequestCulture is used.

QueryStringRequestCultureProviderQueryStringRequestCultureProvider

일부 앱은 쿼리 문자열을 사용하여 /dotnet/api/system.globalization.cultureinfo?view=netcore-3.1을 설정합니다.Some apps will use a query string to set the /dotnet/api/system.globalization.cultureinfo?view=netcore-3.1. cookie 또는 수용-언어 헤더 방식을 사용하는 앱의 경우 URL에 쿼리 문자열을 추가하는 것은 코드 디버깅 및 테스트에 유용합니다.For apps that use the cookie or Accept-Language header approach, adding a query string to the URL is useful for debugging and testing code. 기본적으로 QueryStringRequestCultureProviderRequestCultureProvider 목록에서 첫 번째 지역화 공급자로 등록됩니다.By default, the QueryStringRequestCultureProvider is registered as the first localization provider in the RequestCultureProvider list. cultureui-culture에 쿼리 문자열 매개 변수를 전달합니다.You pass the query string parameters culture and ui-culture. 다음 예제는 특정 문화권(언어 및 지역)을 스페인어/멕시코로 설정합니다.The following example sets the specific culture (language and region) to Spanish/Mexico:

http://localhost:5000/?culture=es-MX&ui-culture=es-MX

둘 중 하나만을 전달하는 경우(culture 또는 ui-culture) 쿼리 문자열 공급자는 전달한 것을 사용하여 두 값을 설정합니다.If you only pass in one of the two (culture or ui-culture), the query string provider will set both values using the one you passed in. 예를 들어 문화권만을 설정하면 CultureUICulture 모두를 설정합니다.For example, setting just the culture will set both the Culture and the UICulture:

http://localhost:5000/?culture=es-MX

CookieRequestCultureProviderCookieRequestCultureProvider

프로덕션 앱은 종종 메커니즘을 제공하여 ASP.NET Core 문화권 cookie로 문화권을 설정합니다.Production apps will often provide a mechanism to set the culture with the ASP.NET Core culture cookie. MakeCookieValue 메서드를 사용하여 cookie를 만듭니다.Use the MakeCookieValue method to create a cookie.

CookieRequestCultureProvider DefaultCookieName은 사용자의 기본 문화권 정보를 추적하는 데 사용되는 기본 cookie 이름을 반환합니다.The CookieRequestCultureProvider DefaultCookieName returns the default cookie name used to track the user's preferred culture information. 기본 cookie 이름은 .AspNetCore.Culture입니다.The default cookie name is .AspNetCore.Culture.

cookie 형식은 c=%LANGCODE%|uic=%LANGCODE%이며, 여기서 cCulture이고 uicUICulture입니다. 예를 들면 다음과 같습니다.The cookie format is c=%LANGCODE%|uic=%LANGCODE%, where c is Culture and uic is UICulture, for example:

c=en-UK|uic=en-US

문화권 정보 및 UI 문화권 중 하나만 지정하는 경우 지정된 문화권은 문화권 정보 및 UI 문화권 모두에 사용됩니다.If you only specify one of culture info and UI culture, the specified culture will be used for both culture info and UI culture.

수용-언어 HTTP 헤더The Accept-Language HTTP header

수용-언어 헤더는 대부분의 브라우저에서 설정할 수 있으며 원래 사용자의 언어를 지정하도록 계획되었습니다.The Accept-Language header is settable in most browsers and was originally intended to specify the user's language. 이 설정은 브라우저가 전송하도록 설정된 것 또는 기본 운영 체제에서 상속한 것을 나타냅니다.This setting indicates what the browser has been set to send or has inherited from the underlying operating system. 브라우저 요청에서 수용-언어 HTTP 헤더는 사용자의 기본 언어를 검색하는 확실한 방법이 아닙니다(브라우저에서 언어 기본 설정 설정 참조).The Accept-Language HTTP header from a browser request isn't an infallible way to detect the user's preferred language (see Setting language preferences in a browser). 프로덕션 앱은 사용자가 선택한 문화권을 사용자 지정하는 방법을 포함해야 합니다.A production app should include a way for a user to customize their choice of culture.

IE에서 수용-언어 HTTP 헤더 설정Set the Accept-Language HTTP header in IE

  1. 기어 아이콘에서 인터넷 옵션을 누릅니다.From the gear icon, tap Internet Options.

  2. 언어를 누릅니다.Tap Languages.

    인터넷 옵션

  3. 언어 기본 설정 설정을 누릅니다.Tap Set Language Preferences.

  4. 언어 추가를 누릅니다.Tap Add a language.

  5. 언어를 추가합니다.Add the language.

  6. 언어를 누른 다음, 위로 이동을 누릅니다.Tap the language, then tap Move Up.

콘텐츠-언어 HTTP 헤더The Content-Language HTTP header

콘텐츠-언어 엔터티 헤더:The Content-Language entity header:

  • 대상 그룹을 위한 언어를 설명하는 데 사용됩니다.Is used to describe the language(s) intended for the audience.
  • 사용자가 사용자 기본 설정 언어에 따라 구별할 수 있습니다.Allows a user to differentiate according to the users' own preferred language.

엔터티 헤더는 HTTP 요청 및 응답에 모두 사용됩니다.Entity headers are used in both HTTP requests and responses.

속성 ApplyCurrentCultureToResponseHeaders을(를) 설정하여 Content-Language 헤더를 추가할 수 있습니다.The Content-Language header can be added by setting the property ApplyCurrentCultureToResponseHeaders.

Content-Language 헤더 추가:Adding the Content-Language header:

  • RequestLocalizationMiddleware가 CurrentUICulture를 사용하여 Content-Language 헤더를 설정할 수 있습니다.Allows the RequestLocalizationMiddleware to set the Content-Language header with the CurrentUICulture.
  • 응답 헤더 Content-Language를 명시적으로 설정하지 않아도 됩니다.Eliminates the need to set the response header Content-Language explicitly.
app.UseRequestLocalization(new RequestLocalizationOptions
{
    ApplyCurrentCultureToResponseHeaders = true
});

사용자 지정 공급자 사용Use a custom provider

소비자가 자신의 언어 및 문화권을 데이터베이스에 저장하도록 하기를 원한다고 가정합니다.Suppose you want to let your customers store their language and culture in your databases. 공급자를 작성하여 사용자에 대한 이러한 값을 조회할 수 있습니다.You could write a provider to look up these values for the user. 다음 코드에서는 사용자 지정 공급자를 추가하는 방법을 보여 줍니다.The following code shows how to add a custom provider:

private const string enUSCulture = "en-US";

services.Configure<RequestLocalizationOptions>(options =>
{
    var supportedCultures = new[]
    {
        new CultureInfo(enUSCulture),
        new CultureInfo("fr")
    };

    options.DefaultRequestCulture = new RequestCulture(culture: enUSCulture, uiCulture: enUSCulture);
    options.SupportedCultures = supportedCultures;
    options.SupportedUICultures = supportedCultures;

    options.AddInitialRequestCultureProvider(new CustomRequestCultureProvider(async context =>
    {
        // My custom request culture logic
        return new ProviderCultureResult("en");
    }));
});

RequestLocalizationOptions를 사용하여 지역화 공급자를 추가하거나 제거합니다.Use RequestLocalizationOptions to add or remove localization providers.

프로그래밍 방식으로 문화권 설정Set the culture programmatically

GitHub에서 이 샘플 Localization.StarterWeb 프로젝트는 Culture를 설정하는 UI를 포함합니다.This sample Localization.StarterWeb project on GitHub contains UI to set the Culture. Views/Shared/_SelectLanguagePartial.cshtml 파일을 통해 지원되는 문화권의 목록에서 문화권을 선택할 수 있습니다.The Views/Shared/_SelectLanguagePartial.cshtml file allows you to select the culture from the list of supported cultures:

@using Microsoft.AspNetCore.Builder
@using Microsoft.AspNetCore.Http.Features
@using Microsoft.AspNetCore.Localization
@using Microsoft.AspNetCore.Mvc.Localization
@using Microsoft.Extensions.Options

@inject IViewLocalizer Localizer
@inject IOptions<RequestLocalizationOptions> LocOptions

@{
    var requestCulture = Context.Features.Get<IRequestCultureFeature>();
    var cultureItems = LocOptions.Value.SupportedUICultures
        .Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName })
        .ToList();
    var returnUrl = string.IsNullOrEmpty(Context.Request.Path) ? "~/" : $"~{Context.Request.Path.Value}";
}

<div title="@Localizer["Request culture provider:"] @requestCulture?.Provider?.GetType().Name">
    <form id="selectLanguage" asp-controller="Home" 
          asp-action="SetLanguage" asp-route-returnUrl="@returnUrl" 
          method="post" class="form-horizontal" role="form">
        <label asp-for="@requestCulture.RequestCulture.UICulture.Name">@Localizer["Language:"]</label> <select name="culture"
          onchange="this.form.submit();"
          asp-for="@requestCulture.RequestCulture.UICulture.Name" asp-items="cultureItems">
        </select>
    </form>
</div>

Views/Shared/_SelectLanguagePartial.cshtml 파일은 레이아웃 파일의 footer 섹션에 추가되므로 모든 보기에 사용할 수 있습니다.The Views/Shared/_SelectLanguagePartial.cshtml file is added to the footer section of the layout file so it will be available to all views:

<div class="container body-content" style="margin-top:60px">
    @RenderBody()
    <hr>
    <footer>
        <div class="row">
            <div class="col-md-6">
                <p>&copy; @System.DateTime.Now.Year - Localization</p>
            </div>
            <div class="col-md-6 text-right">
                @await Html.PartialAsync("_SelectLanguagePartial")
            </div>
        </div>
    </footer>
</div>

SetLanguage 메서드는 문화권 cookie를 설정합니다.The SetLanguage method sets the culture cookie.

[HttpPost]
public IActionResult SetLanguage(string culture, string returnUrl)
{
    Response.Cookies.Append(
        CookieRequestCultureProvider.DefaultCookieName,
        CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
        new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) }
    );

    return LocalRedirect(returnUrl);
}

_SelectLanguagePartial.cshtml을 이 프로젝트에 대한 샘플 코드에 플러그 인할 수 없습니다.You can't plug in the _SelectLanguagePartial.cshtml to sample code for this project. GitHubLocalization.StarterWeb 프로젝트에는 종속성 주입 컨테이너를 통해 Razor 부분에 RequestLocalizationOptions를 흐르도록 하는 코드가 있습니다.The Localization.StarterWeb project on GitHub has code to flow the RequestLocalizationOptions to a Razor partial through the Dependency Injection container.

모델 바인딩 경로 데이터 및 쿼리 문자열Model binding route data and query strings

모델 바인딩 경로 데이터 및 쿼리 문자열의 세계화 동작을 참조하세요.See Globalization behavior of model binding route data and query strings.

세계화 및 지역화 용어Globalization and localization terms

또한 앱을 지역화하는 프로세스에는 최신 소프트웨어 개발에 일반적으로 사용되는 관련 문자 집합에 대한 기본적인 이해 및 관련된 문제에 대한 이해가 필요합니다.The process of localizing your app also requires a basic understanding of relevant character sets commonly used in modern software development and an understanding of the issues associated with them. 모든 컴퓨터가 텍스트를 숫자(코드)로 저장하지만 다른 시스템은 다른 숫자를 사용하여 동일한 텍스트를 저장합니다.Although all computers store text as numbers (codes), different systems store the same text using different numbers. 지역화 프로세스는 특정 문화권/로캘에 대한 앱 UI(사용자 인터페이스) 번역을 참조합니다.The localization process refers to translating the app user interface (UI) for a specific culture/locale.

지역화 가능성은 세계화된 앱이 지역화에 대해 준비가 되어 있는지 확인하기 위한 중간 프로세스입니다.Localizability is an intermediate process for verifying that a globalized app is ready for localization.

문화권 이름에 대한 RFC 4646 형식은 <languagecode2>-<country/regioncode2>이며, 여기서 <languagecode2>는 언어 코드이며 <country/regioncode2>는 하위 문화권 코드입니다.The RFC 4646 format for the culture name is <languagecode2>-<country/regioncode2>, where <languagecode2> is the language code and <country/regioncode2> is the subculture code. 예를 들어 스페인어(칠레)의 경우 es-CL, 영어(미국)의 경우 en-US 및 영어(오스트레일리아)의 경우 en-AU입니다.For example, es-CL for Spanish (Chile), en-US for English (United States), and en-AU for English (Australia). RFC 4646은 언어와 관련된 ISO 639 두 문자의 소문자 문화권 코드와 국가 또는 지역과 관련된 ISO 3166 두 문자의 대문자 하위 문화권 코드의 조합입니다.RFC 4646 is a combination of an ISO 639 two-letter lowercase culture code associated with a language and an ISO 3166 two-letter uppercase subculture code associated with a country or region. /previous-versions/commerce-server/ee825488(v=cs.20)을 참조하세요.See /previous-versions/commerce-server/ee825488(v=cs.20).

국제화는 종종 "I18N"으로 단축됩니다.Internationalization is often abbreviated to "I18N". 약어는 첫 번째 및 마지막 문자와 둘 사이의 문자 수를 사용하므로 18은 첫 번째 "I"와 마지막 "N" 사이의 문자 수를 의미합니다.The abbreviation takes the first and last letters and the number of letters between them, so 18 stands for the number of letters between the first "I" and the last "N". 세계화(G11N) 및 지역화(L10N)에도 동일하게 적용됩니다.The same applies to Globalization (G11N), and Localization (L10N).

용어:Terms:

  • 세계화(G11N): 앱이 다른 언어 및 지역을 지원하도록 만드는 프로세스입니다.Globalization (G11N): The process of making an app support different languages and regions.
  • 지역화(L10N): 지정된 언어 및 지역에 대해 앱을 사용자 지정하는 프로세스입니다.Localization (L10N): The process of customizing an app for a given language and region.
  • 국제화(I18N): 세계화와 지역화를 모두 설명합니다.Internationalization (I18N): Describes both globalization and localization.
  • 문화권: 언어이며 경우에 따라 지역입니다.Culture: It's a language and, optionally, a region.
  • 중립 문화권: 지정한 언어가 있지만 지정된 지역이 없는 문화권입니다.Neutral culture: A culture that has a specified language, but not a region. (예: "en", "es")(for example "en", "es")
  • 특정 문화권: 지정된 언어 및 지역이 있는 문화권입니다.Specific culture: A culture that has a specified language and region. (예: "en-US", "en-GB", "es-CL")(for example "en-US", "en-GB", "es-CL")
  • 부모 문화권: 특정 문화권을 포함하는 중립 문화권입니다.Parent culture: The neutral culture that contains a specific culture. (예: "en"은 "en-US" 및 "en-GB"의 부모 문화권)(for example, "en" is the parent culture of "en-US" and "en-GB")
  • 로캘: 로캘은 문화권과 동일합니다.Locale: A locale is the same as a culture.

참고

십진수 필드에는 십진수 쉼표를 입력하지 못할 수도 있습니다.You may not be able to enter decimal commas in decimal fields. 소수점으로 쉼표(“,”)를 사용하는 영어가 아닌 로캘 및 미국 영어가 아닌 날짜 형식에 대해 jQuery 유효성 검사를 지원하려면 앱을 전역화하는 단계를 수행해야 합니다.To support jQuery validation for non-English locales that use a comma (",") for a decimal point, and non US-English date formats, you must take steps to globalize your app. 소수점 추가에 대한 지침은 이 GitHub 문제 4076을 참조하세요.See this GitHub issue 4076 for instructions on adding decimal comma.

참고

ASP.NET Core 3.0 이전에는 요청된 문화권이 지원되지 않는 경우 웹앱이 요청당 LogLevel.Warning 형식의 로그 하나를 작성합니다.Prior to ASP.NET Core 3.0 web apps write one log of type LogLevel.Warning per request if the requested culture is unsupported. 요청당 하나의 LogLevel.Warning을 로깅하면 중복된 정보로 로그 파일이 커질 수 있습니다.Logging one LogLevel.Warning per request is can make large log files with redundant information. 이 동작은 ASP.NET 3.0에서 변경되었습니다.This behavior has been changed in ASP.NET 3.0. RequestLocalizationMiddlewareLogLevel.Debug 형식의 로그를 작성하므로 프로덕션 로그의 크기가 줄어듭니다.The RequestLocalizationMiddleware writes a log of type LogLevel.Debug, which reduces the size of production logs.

추가 자료Additional resources