대규모 .NET 프로젝트에서 다국어 / 세계화를 구현하는 가장 좋은 방법


87

곧 대규모 C # 프로젝트에서 작업 할 예정이며 처음부터 다국어 지원을 구축하고 싶습니다. 나는 놀았고 각 언어에 대해 별도의 리소스 파일을 사용하여 작동하게 한 다음 리소스 관리자를 사용하여 문자열을로드 할 수 있습니다.

제가 살펴볼 수있는 다른 좋은 접근 방법이 있습니까?

답변:


91

리소스와 함께 별도의 프로젝트 사용

API, MVC, 프로젝트 라이브러리 (핵심 기능), WPF, UWP 및 Xamarin을 포함 하는 12 개의 24 개 프로젝트가 포함 된 현재 솔루션이있는 경험을 통해이를 알 수 있습니다 . 내가 그렇게하는 가장 좋은 방법이라고 생각하므로이 긴 게시물을 읽을 가치가 있습니다. VS 도구의 도움으로 쉽게 내보내고 가져올 수 있으며 번역 대행사로 보내거나 다른 사람이 검토 할 수 있습니다.

2018 년 2 월 수정 : 여전히 강력 해지 면서 .NET Standard 라이브러리로 변환하면 .NET Framework 및 NET Core에서도 사용할 수 있습니다. 예를 들어 angular에서 사용할 수 있도록 JSON으로 변환하기위한 추가 섹션을 추가했습니다.

EDIT 2019 : Xamarin을 통해 앞으로도 모든 플랫폼에서 계속 작동합니다. 예 : resx 파일을 사용하기위한 Xamarin.Forms 조언. (아직 Xamarin.Forms에서 앱을 개발하지 않았지만 시작하는 방법에 대한 자세한 설명은 Xamarin.Forms Documentation ). JSON으로 변환하는 것과 마찬가지로 Xamarin.Android 용 .xml 파일로 변환 할 수도 있습니다.

EDIT 2019 (2) : WPF에서 UWP로 업그레이드하는 동안 UWP에서 .resw콘텐츠는 동일하지만 사용법이 다른 다른 파일 형식을 사용하는 것을 선호한다는 것을 발견했습니다 . 내 의견으로 는 기본 솔루션 보다 더 잘 작동하는 다른 방법을 찾았습니다 .

EDIT 2020 : 여러 언어 프로젝트가 필요할 수있는 대규모 (modulair) 프로젝트에 대한 몇 가지 제안을 업데이트했습니다.

그래서 그것에 도달합시다.

프로

  • 거의 모든 곳에서 강력하게 입력되었습니다.
  • WPF에서는 ResourceDirectories.
  • 테스트 한 한 ASP.NET, 클래스 라이브러리, WPF, Xamarin, .NET Core, .NET Standard에 대해 지원됩니다.
  • 추가 타사 라이브러리가 필요하지 않습니다.
  • 문화 대체 지원 : en-US-> en.
  • 백엔드뿐만 아니라 WPF 용 XAML 및 MVC 용 .cshtml에서도 작동합니다.
  • 변경하여 언어를 쉽게 조작 Thread.CurrentThread.CurrentCulture
  • 검색 엔진은 다른 언어로 크롤링 할 수 있으며 사용자는 언어 별 URL을 보내거나 저장할 수 있습니다.

단점

  • WPF XAML은 때때로 버그가 있으며 새로 추가 된 문자열이 직접 표시되지 않습니다. Rebuild는 임시 수정 (vs2015)입니다.
  • UWP XAML은 인텔리 센스 제안을 표시하지 않으며 디자인하는 동안 텍스트를 표시하지 않습니다.
  • 말해.

설정

솔루션에서 언어 프로젝트를 만들고 MyProject.Language 와 같은 이름을 지정 합니다. Resources라는 폴더를 추가하고 해당 폴더에 두 개의 Resources 파일 (.resx)을 만듭니다. 하나는 Resources.resx 이고 다른 하나는 Resources.en.resx (또는 특정의 경우 .en-GB.resx)입니다. 내 구현에서 기본 언어로 NL (네덜란드어) 언어가 있으므로 첫 번째 파일에, 영어는 두 번째 파일에 들어갑니다.

설정은 다음과 같습니다.

언어 설정 프로젝트

Resources.resx의 속성은 다음과 같아야합니다. 속성

사용자 지정 도구 네임 스페이스가 프로젝트 네임 스페이스로 설정되어 있는지 확인합니다. 그 이유는 WPF에서 ResourcesXAML 내부를 참조 할 수 없기 때문 입니다.

리소스 파일 내에서 액세스 수정자를 Public으로 설정합니다.

액세스 수정 자

이렇게 큰 애플리케이션 (다른 모듈이라고합시다)이있는 경우 위와 같이 여러 프로젝트를 만드는 것을 고려할 수 있습니다. 이 경우 키와 리소스 클래스에 특정 모듈을 접두사로 붙일 수 있습니다. Visual Studio 용 최고의 언어 편집기를 사용 하여 모든 파일을 단일 개요로 결합합니다.

다른 프로젝트에서 사용

프로젝트 참조 : References-> Add Reference-> Prjects \ Solutions를 마우스 오른쪽 버튼으로 클릭합니다.

파일에서 네임 스페이스 사용 : using MyProject.Language;

백엔드에서 그렇게 사용하십시오. string someText = Resources.orderGeneralError; Resources라는 다른 것이 있으면 전체 네임 스페이스에 넣으십시오.

MVC에서 사용

MVC에서는 언어를 설정하고 싶은대로 할 수 있지만 다음과 같이 설정할 수있는 매개 변수화 된 URL을 사용했습니다.

RouteConfig.cs 다른 매핑 아래

routes.MapRoute(
    name: "Locolized",
    url: "{lang}/{controller}/{action}/{id}",
    constraints: new { lang = @"(\w{2})|(\w{2}-\w{2})" },   // en or en-US
    defaults: new { controller = "shop", action = "index", id = UrlParameter.Optional }
);

FilterConfig.cs은 추가, 그렇다면 (추가해야 할 수 있습니다 FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);받는 사람 Application_start()의 방법Global.asax

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new ErrorHandler.AiHandleErrorAttribute());
        //filters.Add(new HandleErrorAttribute());
        filters.Add(new LocalizationAttribute("nl-NL"), 0);
    }
}

LocalizationAttribute

public class LocalizationAttribute : ActionFilterAttribute
{
    private string _DefaultLanguage = "nl-NL";
    private string[] allowedLanguages = { "nl", "en" };

    public LocalizationAttribute(string defaultLanguage)
    {
        _DefaultLanguage = defaultLanguage;
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        string lang = (string) filterContext.RouteData.Values["lang"] ?? _DefaultLanguage;
        LanguageHelper.SetLanguage(lang);
    }
}

LanguageHelper 는 문화 정보 만 설정합니다.

//fixed number and date format for now, this can be improved.
public static void SetLanguage(LanguageEnum language)
{
    string lang = "";
    switch (language)
    {
        case LanguageEnum.NL:
            lang = "nl-NL";
            break;
        case LanguageEnum.EN:
            lang = "en-GB";
            break;
        case LanguageEnum.DE:
            lang = "de-DE";
            break;
    }
    try
    {
        NumberFormatInfo numberInfo = CultureInfo.CreateSpecificCulture("nl-NL").NumberFormat;
        CultureInfo info = new CultureInfo(lang);
        info.NumberFormat = numberInfo;
        //later, we will if-else the language here
        info.DateTimeFormat.DateSeparator = "/";
        info.DateTimeFormat.ShortDatePattern = "dd/MM/yyyy";
        Thread.CurrentThread.CurrentUICulture = info;
        Thread.CurrentThread.CurrentCulture = info;
    }
    catch (Exception)
    {

    }
}

.cshtml에서의 사용법

@using MyProject.Language;
<h3>@Resources.w_home_header</h3>

또는 usings를 정의하지 않으려면 전체 네임 스페이스를 채우거나 /Views/web.config 아래에 네임 스페이스를 정의 할 수 있습니다.

<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
  <namespaces>
    ...
    <add namespace="MyProject.Language" />
  </namespaces>
</pages>
</system.web.webPages.razor>

이 MVC 구현 소스 자습서 : Awesome Tutorial Blog

모델에 클래스 라이브러리 사용

백엔드 사용은 동일하지만 속성에서 사용하는 예일뿐입니다.

using MyProject.Language;
namespace MyProject.Core.Models
{
    public class RegisterViewModel
    {
        [Required(ErrorMessageResourceName = "accountEmailRequired", ErrorMessageResourceType = typeof(Resources))]
        [EmailAddress]
        [Display(Name = "Email")]
        public string Email { get; set; }
    }
}

reshaper가 있으면 주어진 리소스 이름이 존재하는지 자동으로 확인합니다. 형식 안전성을 선호하는 경우 T4 템플릿을 사용하여 열거 형을 생성 할 수 있습니다.

WPF에서 사용.

물론 MyProject.Language 네임 스페이스 에 대한 참조를 추가하면 백엔드에서 사용하는 방법을 알고 있습니다.

XAML에서 Window 또는 UserControl의 헤더 안에 다음 lang과 같은 네임 스페이스 참조를 추가합니다 .

<UserControl x:Class="Babywatcher.App.Windows.Views.LoginView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:MyProject.App.Windows.Views"
              xmlns:lang="clr-namespace:MyProject.Language;assembly=MyProject.Language" <!--this one-->
             mc:Ignorable="d" 
            d:DesignHeight="210" d:DesignWidth="300">

그런 다음 레이블 내부 :

    <Label x:Name="lblHeader" Content="{x:Static lang:Resources.w_home_header}" TextBlock.FontSize="20" HorizontalAlignment="Center"/>

강력한 형식이므로 리소스 문자열이 있는지 확인합니다. 때때로 설치 중에 프로젝트를 다시 컴파일해야 할 수 있습니다. WPF는 때때로 새 네임 스페이스로 버그가 있습니다.

WPF에 대한 한 가지 더, App.xaml.cs. 직접 구현하거나 (설치 중에 선택) 시스템이 결정하도록 할 수 있습니다.

UWP에서 사용

UWP에서 Microsoft는 이 솔루션을 사용하므로 새 리소스 파일을 만들어야합니다. 또한 x:UidXAML에서 컨트롤을 리소스의 키로 설정하기를 원하기 때문에 텍스트를 다시 사용할 수 없습니다 . 그리고 당신의 자원에서 당신은 의 텍스트 Example.Text를 채우기 위해해야 TextBlock합니다. 내 리소스 파일을 재사용하고 싶기 때문에 해당 솔루션이 전혀 마음에 들지 않았습니다. 결국 나는 다음 해결책을 생각해 냈습니다. 나는 오늘 (2019-09-26) 이것을 발견했기 때문에 이것이 원하는대로 작동하지 않으면 다른 것을 가지고 돌아올 수 있습니다.

프로젝트에 다음을 추가하십시오.

using Windows.UI.Xaml.Resources;

public class MyXamlResourceLoader : CustomXamlResourceLoader
{
    protected override object GetResource(string resourceId, string objectType, string propertyName, string propertyType)
    {
        return MyProject.Language.Resources.ResourceManager.GetString(resourceId);
    }
}

App.xaml.cs생성자에 다음 을 추가하십시오 .

CustomXamlResourceLoader.Current = new MyXamlResourceLoader();

앱에서 원하는 곳 어디에서나 다음을 사용하여 언어를 변경하십시오.

ApplicationLanguages.PrimaryLanguageOverride = "nl";
Frame.Navigate(this.GetType());

UI를 새로 고치려면 마지막 줄이 필요합니다. 이 프로젝트를 계속 진행하는 동안이 작업을 두 번해야한다는 것을 알았습니다. 사용자가 처음 시작할 때 언어 선택으로 끝날 수 있습니다. 그러나 이것은 Windows Store를 통해 배포되므로 일반적으로 언어는 시스템 언어와 동일합니다.

그런 다음 XAML에서 사용합니다.

<TextBlock Text="{CustomResource ExampleResourceKey}"></TextBlock>

Angular에서 사용 (JSON으로 변환)

요즘에는 Angular와 같은 프레임 워크를 구성 요소와 결합하여 cshtml없이 사용하는 것이 더 일반적입니다. 번역은 json 파일에 저장되며, 작동 방식을 다루지는 않을 것 입니다. 각도 다중 번역 대신 ngx-translate 를 강력히 권장 합니다. 따라서 번역을 JSON 파일로 변환하려면 매우 쉽습니다. 리소스 파일을 json 파일로 변환하는 T4 템플릿 스크립트를 사용합니다. 몇 가지 수정이 필요하므로 구문을 읽고 올바르게 사용하려면 T4 편집기 를 설치하는 것이 좋습니다 .

단 한 가지주의 할 점 : 데이터를 생성, 복사, 정리하고 다른 언어로 생성하는 것은 불가능합니다. 따라서 아래 코드를 사용중인 언어 수만큼 복사하고 '// 여기에서 언어 선택'앞에 항목을 변경해야합니다. 현재는이 문제를 해결할 시간이 없지만 나중에 업데이트 될 것입니다 (관심있는 경우).

경로 : MyProject.Language / T4 / CreateLocalizationEN.tt

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="System.Windows.Forms" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Resources" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.ComponentModel.Design" #>
<#@ output extension=".json" #>
<#


var fileNameNl = "../Resources/Resources.resx";
var fileNameEn = "../Resources/Resources.en.resx";
var fileNameDe = "../Resources/Resources.de.resx";
var fileNameTr = "../Resources/Resources.tr.resx";

var fileResultName = "../T4/CreateLocalizationEN.json";//choose language here
var fileResultPath = Path.Combine(Path.GetDirectoryName(this.Host.ResolvePath("")), "MyProject.Language", fileResultName);
//var fileDestinationPath = "../../MyProject.Web/ClientApp/app/i18n/";

var fileNameDestNl = "nl.json";
var fileNameDestEn = "en.json";
var fileNameDestDe = "de.json";
var fileNameDestTr = "tr.json";

var pathBaseDestination = Directory.GetParent(Directory.GetParent(this.Host.ResolvePath("")).ToString()).ToString();

string[] fileNamesResx = new string[] {fileNameEn }; //choose language here
string[] fileNamesDest = new string[] {fileNameDestEn }; //choose language here

for(int x = 0; x < fileNamesResx.Length; x++)
{
    var currentFileNameResx = fileNamesResx[x];
    var currentFileNameDest = fileNamesDest[x];
    var currentPathResx = Path.Combine(Path.GetDirectoryName(this.Host.ResolvePath("")), "MyProject.Language", currentFileNameResx);
    var currentPathDest =pathBaseDestination + "/MyProject.Web/ClientApp/app/i18n/" + currentFileNameDest;
    using(var reader = new ResXResourceReader(currentPathResx))
    {
        reader.UseResXDataNodes = true;
#>
        {
<#
            foreach(DictionaryEntry entry in reader)
            {
                var name = entry.Key;
                var node = (ResXDataNode)entry.Value;
                var value = node.GetValue((ITypeResolutionService) null); 
                 if (!String.IsNullOrEmpty(value.ToString())) value = value.ToString().Replace("\n", "");
                 if (!String.IsNullOrEmpty(value.ToString())) value = value.ToString().Replace("\r", "");
#>
            "<#=name#>": "<#=value#>",
<#

    
            }
#>
        "WEBSHOP_LASTELEMENT": "just ignore this, for testing purpose"
        }
<#
    }
    File.Copy(fileResultPath, currentPathDest, true);
}


#>

modulair 응용 프로그램이 있고 여러 언어 프로젝트를 만들라는 제 제안을 따랐다면 각각에 대해 T4 파일을 만들어야합니다. json 파일이 논리적으로 정의되어 있는지 확인하십시오. 반드시이어야 en.json할 필요는 없으며 example-en.json. ngx-translate 와 함께 사용하기 위해 여러 json 파일을 결합하려면 여기 의 지침을 따르십시오.

Xamarin.Android에서 사용

위의 업데이트에서 설명한 것처럼 Angular / JSON과 동일한 방법을 사용합니다. 하지만 Android는 XML 파일을 사용하므로 이러한 XML 파일을 생성하는 T4 파일을 작성했습니다.

경로 : MyProject.Language / T4 / CreateAppLocalizationEN.tt

#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="System.Windows.Forms" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Resources" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.ComponentModel.Design" #>
<#@ output extension=".xml" #>
<#
var fileName = "../Resources/Resources.en.resx";
var fileResultName = "../T4/CreateAppLocalizationEN.xml";
var fileResultRexPath = Path.Combine(Path.GetDirectoryName(this.Host.ResolvePath("")), "MyProject.Language", fileName);
var fileResultPath = Path.Combine(Path.GetDirectoryName(this.Host.ResolvePath("")), "MyProject.Language", fileResultName);

    var fileNameDest = "strings.xml";

    var pathBaseDestination = Directory.GetParent(Directory.GetParent(this.Host.ResolvePath("")).ToString()).ToString();

    var currentPathDest =pathBaseDestination + "/MyProject.App.AndroidApp/Resources/values-en/" + fileNameDest;

    using(var reader = new ResXResourceReader(fileResultRexPath))
    {
        reader.UseResXDataNodes = true;
        #>
        <resources>
        <#

                foreach(DictionaryEntry entry in reader)
                {
                    var name = entry.Key;
                    //if(!name.ToString().Contains("WEBSHOP_") && !name.ToString().Contains("DASHBOARD_"))//only include keys with these prefixes, or the country ones.
                    //{
                    //  if(name.ToString().Length != 2)
                    //  {
                    //      continue;
                    //  }
                    //}
                    var node = (ResXDataNode)entry.Value;
                    var value = node.GetValue((ITypeResolutionService) null); 
                     if (!String.IsNullOrEmpty(value.ToString())) value = value.ToString().Replace("\n", "");
                     if (!String.IsNullOrEmpty(value.ToString())) value = value.ToString().Replace("\r", "");
                     if (!String.IsNullOrEmpty(value.ToString())) value = value.ToString().Replace("&", "&amp;");
                     if (!String.IsNullOrEmpty(value.ToString())) value = value.ToString().Replace("<<", "");
                     //if (!String.IsNullOrEmpty(value.ToString())) value = value.ToString().Replace("'", "\'");
#>
              <string name="<#=name#>">"<#=value#>"</string>
<#      
                }
#>
            <string name="WEBSHOP_LASTELEMENT">just ignore this</string>
<#
        #>
        </resources>
        <#
        File.Copy(fileResultPath, currentPathDest, true);
    }

#>

Android는 values-xx폴더에서 작동 하므로 위의 폴더는 영어 용입니다 values-en. 그러나 values폴더에 들어가는 기본값도 생성해야 합니다. T4 템플릿 위에 복사하고 위 코드에서 폴더를 변경하십시오.

이제 모든 프로젝트에 대해 하나의 단일 리소스 파일을 사용할 수 있습니다. 이것은 모든 것을 엑셀 문서로 아주 쉽게 내보내고 누군가가 그것을 번역하고 다시 가져올 수있게합니다.

파일로 멋지게 작동 하는 이 놀라운 VS 확장 기능 덕분에 특별히 감사드립니다 resx. 그의 멋진 작품을 위해 그에게 기부 하는 것을 고려 해보세요 (저는 그것과 아무 관련이 없으며 확장 프로그램을 좋아합니다).


1. 배포 후 더 많은 언어를 추가하려면 어떻게해야합니까? Mylanguage에 리소스를 더 추가하고 다시 컴파일 한 다음 다시 배포하는 방법은 무엇입니까? (2) 번역에 사용한 IDE 또는 도구가 있습니까 (winform에 40 개 이상의 양식이 있습니다), 공유 할 수 있습니까? (3) 시도했지만 아랍어로 문화를 변경했을 때 번역이되지 않았습니다. 질문을 만들어 알려
Smith

5
1 : Resources.xx.resx를 복제하고 xx를 변경하고 switch 문이있는 모든 곳에서 언어를 추가합니다. 2 I Use ResxManager (by TomEnglert) 확장 기능은 Tools-> Extensions를 통해 설치할 수 있습니다. 언어를 서로 옆에 두는 좋은 방법이지만 실제 번역은 다른 사람이 수행합니다 (ResxManager를 사용하여 Excel로 쉽게 내보내기 및 가져 오기). 3. 마지막으로도 하나를 추가하여 발생했습니다. 위에 나열된 모든 파일을 확인하되 일부 중단 점을 확인하십시오. 나는 WinForms에서 이것을 사용하지 않았습니다.
CularBytes

13
내 답변을 찬성 할 수 있습니까? WPF에서 언어 간 전환에 대한 버그를 수정하기 위해 어리석게 내 대답을 확인해야했습니다. -.-
CularBytes

1
@TiagoBrenck 안녕하세요,이 특정 상황에서만 영어가 기본 언어 인 경우 resources.en-gb.resx 파일을 만들고 거기에 1 % 변경 사항을 추가 할 수 있습니다. 기본적으로 en-gb 언어가 선택되고 단어가 번역되지 않으면 기본 언어 (resources.resx)가 사용됩니다.
CularBytes

1
리소스 파일의 키를 어떻게 구성 했습니까? 리소스 파일을 하나만 사용하는 것을 보았고, 당신에 따르면 거대한 앱이 있는데 어떻게 키를 분할 했습니까? "Feature.MyMessage"또는 "Area.Feature.MyMessage"와 같은 형식
Francesco Venturini

21

여러 가지 다른 접근 방식을 사용하여 구현 된 프로젝트를 보았습니다. 각각의 장점과 단점이 있습니다.

  • 하나는 구성 파일에서 수행했습니다 (내가 가장 좋아하는 파일이 아님)
  • 하나는 데이터베이스를 사용하여 수행했습니다. 이것은 꽤 잘 작동했지만 무엇을 유지해야하는지 아는 데있어서 고통이었습니다.
  • 하나는 당신이 제안한 방식으로 리소스 파일을 사용했으며 내가 가장 좋아하는 접근 방식이라고 말해야합니다.
  • 가장 기본적인 것은 문자열로 가득 찬 포함 파일을 사용하여 수행했습니다.

나는 당신이 선택한 자원 방법이 많은 의미가 있다고 말하고 싶습니다. 이런 일을하는 더 좋은 방법이 있는지 자주 궁금해해서 다른 사람들의 대답도 보는 것도 재미있을 것입니다. 나는 바로 여기 SO를 포함하여 리소스 사용 방법을 가리키는 수많은 리소스를 보았습니다 .


5

나는 "최선의 방법"이 있다고 생각하지 않는다. 실제로 구축하는 기술 및 응용 프로그램 유형에 따라 다릅니다.

웹앱은 다른 포스터가 제안한대로 데이터베이스에 정보를 저장할 수 있지만 별도의 리소스 파일을 사용하는 것이 좋습니다. 그것은 당신의 소스에서 분리 된 리소스 파일 입니다. 리소스 파일을 분리하면 동일한 파일에 대한 경합이 줄어들고 프로젝트가 커짐에 따라 현지화가 비즈니스 로직과 별도로 수행 될 수 있습니다. (프로그래머 및 번역가).

Microsoft WinForm 및 WPF 전문가는 각 로캘에 맞게 사용자 지정된 별도의 리소스 어셈블리를 사용할 것을 권장합니다.

콘텐츠에 맞게 UI 요소의 크기를 조정하는 WPF의 기능은 필요한 레이아웃 작업을 줄여줍니다. 예 : (일본어 단어는 영어보다 훨씬 짧습니다).

WPF를 고려중인 경우 : 이 msdn 기사읽는 것이 좋습니다 . 사실 WPF 지역화 도구 인 msbuild, locbaml (및 엑셀 스프레드 시트)을 사용하는 것이 지루하지만 작동합니다.

약간 관련된 것 : 내가 직면하는 일반적인 문제는 오류 코드가 아닌 오류 메시지 (보통 영어)를 보내는 레거시 시스템을 통합하는 것입니다. 이것은 레거시 시스템을 변경하거나 백엔드 문자열을 내 오류 코드에 매핑 한 다음 현지화 된 문자열로 매핑합니다. 오류 코드는 현지화 친구입니다.


4

+1 데이터베이스

앱의 양식은 데이터베이스가 수정 된 경우 즉시 다시 번역 할 수도 있습니다.

모든 컨트롤이 XML 파일 (양식당 하나씩)에 언어 리소스 ID로 매핑되었지만 모든 ID가 데이터베이스에있는 시스템을 사용했습니다.

기본적으로 각 컨트롤에 ID (인터페이스 구현 또는 VB6의 태그 속성 사용)를 유지하는 대신 .NET에서는 리플렉션을 통해 컨트롤 트리를 쉽게 검색 할 수 있다는 사실을 사용했습니다. 양식이로드 될 때 프로세스가 누락 된 경우 XML 파일을 빌드합니다. XML 파일은 컨트롤을 해당 리소스 ID에 매핑하므로 단순히 입력하고 데이터베이스에 매핑하면됩니다. 이것은 태그가 지정되지 않았거나 다른 ID로 분할해야하는 경우 컴파일 된 바이너리를 변경할 필요가 없음을 의미합니다 (명사와 동사로 사용될 수있는 영어로 된 일부 단어는 두 개의 다른 단어로 번역해야 할 수 있음) 딕셔너리에서 재사용 할 수 없지만 초기 ID 할당 중에이를 발견하지 못할 수 있습니다.

앱이 더 많이 관여하는 유일한 경우는 삽입 점이있는 단계가 사용되는 경우입니다.

데이터베이스 번역 소프트웨어는 누락 된 번역 등을 쉽게 처리 할 수있는 다양한 워크 플로 옵션이있는 기본 CRUD 유지 관리 화면이었습니다.


나는 당신의 방법을 좋아합니다. xml 파일이 어떻게 생성되고 데이터베이스에 매핑되는지 알려 주실 수 있습니까?
Smith

Form_Load 등에서 번역 함수는 양식 인스턴스에서 호출되었습니다. 해당 양식의 XML 파일이로드되었습니다. 존재하지 않으면 생성되었습니다. 나는 스키마를 가지고 있지 않지만 기본적으로 양식의 컨트롤 이름을 번역 ID에 매핑했습니다. 따라서 XML 파일에없는 양식의 모든 컨트롤은 번역 ID가없는 항목을 가져옵니다. 요청시 생성되므로 양식을 만들고 누락 된 컨트롤에 대한 XML 파일을 빌드하거나 업데이트하는 앱을 실행하기 만하면됩니다. 그런 다음 항목의 번역 ID를 입력합니다.
Cade Roux

4

나는 수색하고 있고 나는 이것을 발견했다 :

WPF 또는 Silverlight를 사용하는 경우 여러 가지 이유로 WPF LocalizationExtension 을 사용할 수 있습니다 .

IT의 오픈 소스 무료 (그리고 무료로 유지 될 것임)는 진정한 안정 상태입니다.

Windows 응용 프로그램에서 다음과 같이 할 수 있습니다.

public partial class App : Application  
{  
     public App()  
     {             
     }  
 
     protected override void OnStartup(StartupEventArgs e)  
     {  
         Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("de-DE"); ;  
         Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("de-DE"); ;  
 
          FrameworkElement.LanguageProperty.OverrideMetadata(  
              typeof(FrameworkElement),  
              new FrameworkPropertyMetadata(  
                  XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));  
          base.OnStartup(e);  
    }  
} 

그리고 나는 Wep Page에서 aproach가 같을 수 있다고 생각합니다.

행운을 빕니다!


2

여러 리소스 파일을 가지고 갈 것입니다. 구성하기가 그렇게 어렵지 않습니다. 사실 저는 최근에 양식 언어 리소스 파일과 함께 전역 언어 기반 리소스 파일을 설정하는 것과 관련된 유사한 질문에 답변했습니다.

Visual Studio 2008의 지역화

적어도 WinForm 개발을위한 최선의 접근 방식이라고 생각합니다.


리소스의 단점은 언어를 전환하려면 다시 시작해야한다는 것입니다. 아마도 대부분의 사람들에게 받아 들여질 것입니다. 그러나 그것은 내 애완 동물입니다 ...
Roman Starkov

2

Sisulizer 와 같은 상용 도구를 사용할 수 있습니다 . 각 언어에 대한 위성 어셈블리를 생성합니다. 주의해야 할 사항은 양식 클래스 이름을 난독 화하지 않는 것입니다 (난 독자를 사용하는 경우).


0

대부분의 오픈 소스 프로젝트 는 이러한 목적으로 GetText 를 사용 합니다. 나는 그것이 전에 .Net 프로젝트에서 어떻게 그리고 사용되었는지를 모른다.


0

다국어 지원을 위해 사용자 지정 공급자를 사용하고 모든 텍스트를 데이터베이스 테이블에 넣습니다. 웹 응용 프로그램을 업데이트하지 않고 데이터베이스에서 텍스트를 업데이트 할 때 가끔 캐싱 문제가 발생한다는 점을 제외하면 잘 작동합니다.


0

표준 리소스 파일이 더 쉽습니다. 그러나 조회 테이블과 같은 언어 종속 데이터가있는 경우 두 개의 리소스 세트를 관리해야합니다.

나는 그것을하지 않았지만 다음 프로젝트에서는 데이터베이스 리소스 공급자를 구현할 것입니다. MSDN에서 수행하는 방법을 찾았습니다.

http://msdn.microsoft.com/en-us/library/aa905797.aspx

이 구현도 발견했습니다.

DBResource 공급자

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.