Найкращий спосіб реалізації багатомовності / глобалізації у великому .NET-проекті


86

Незабаром я буду працювати над великим проектом c # і хотів би створити багатомовну підтримку з самого початку. Я погрався і можу змусити його працювати, використовуючи окремий файл ресурсів для кожної мови, а потім використовуйте менеджер ресурсів для завантаження рядків.

Чи є якісь інші хороші підходи, на які я міг би поглянути?

Відповіді:


88

Використовуйте окремий проект із ресурсами

Я можу сказати це з досвіду, маючи поточне рішення з 12 24 проектами, що включає API, MVC, бібліотеки проектів (основні функціональні можливості), WPF, UWP та Xamarin. Варто прочитати цю довгу публікацію, оскільки я вважаю, що це найкращий спосіб це зробити. За допомогою інструментів VS, які можна легко експортувати та імпортувати, надсилати до бюро перекладів або переглядати іншими людьми.

РЕДАКТУВАТИ 02/2018: Перетворення його на стандартну бібліотеку .NET дає змогу навіть використовувати її в .NET Framework та NET Core. Я додав додатковий розділ для перетворення його в JSON, щоб, наприклад, angular міг його використовувати.

EDIT 2019: Надалі з Xamarin це все ще працює на всіх платформах. Наприклад, Xamarin. Формує поради щодо використання файлів resx. (Я ще не розробляв додаток у Xamarin.Forms, але документація, яка є деталізованою, щоб просто розпочати, охоплює її: Xamarin.Forms Documentation ). Подібно до перетворення його в JSON, ми можемо також перетворити його у файл .xml для Xamarin.Android.

EDIT 2019 (2): Під час оновлення до UWP з WPF я зіткнувся з тим, що в UWP вони вважають за краще використовувати інший тип файлу .resw, тобто з точки зору вмісту ідентичний, але використання різне. Я знайшов інший спосіб зробити це, який, на мій погляд, працює краще, ніж рішення за замовчуванням .

EDIT 2020: оновлено деякі пропозиції щодо більших (модульних) проектів, які можуть потребувати багатомовних проектів.

Отже, давайте дійдемо до цього.

Про

  • Сильно друкується майже скрізь.
  • У WPF вам не доводиться мати справу ResourceDirectories.
  • Підтримується для ASP.NET, бібліотек класів, WPF, Xamarin, .NET Core, .NET Standard, наскільки я тестував.
  • Не потрібні додаткові сторонні бібліотеки.
  • Підтримує запасний варіант культури: en-US -> en.
  • Не тільки бек-енд, він працює також у XAML для WPF та Xamarin.Forms, у .cshtml для MVC.
  • Легко маніпулювати мовою, змінюючи Thread.CurrentThread.CurrentCulture
  • Пошукові системи можуть сканувати різними мовами, а користувач може надсилати або зберігати URL-адреси для певної мови.

Кон

  • WPF XAML іноді глючить, нещодавно додані рядки не відображаються безпосередньо. Відновити - це тимчасове виправлення (vs2015).
  • UWP XAML не відображає суперечливих пропозицій і не відображає текст під час проектування.
  • Скажи мені.

Налаштування

Створіть мовний проект у своєму рішенні, дайте йому назву, як MyProject.Language . Додайте до неї папку, яка називається Ресурси, і в цій папці створіть два файли Ресурсів (.resx). Один з них називається Resources.resx, а інший - Resources.en.resx (або .en-GB.resx для конкретного). У моїй реалізації я використовую мову NL (голландська) як мову за замовчуванням, так що це йде у моєму першому файлі, а англійська йде у моєму другому файлі.

Налаштування має виглядати так:

проект налаштування мови

Властивості Resources.resx мають бути: властивості

Переконайтеся, що для спеціального простору імен інструментів встановлено простір імен проекту. Причиною цього є те, що у WPF ви не можете посилатися на Resourcesвнутрішній XAML.

А всередині файлу ресурсу встановіть модифікатор доступу на Public:

модифікатор доступу

Якщо у вас такий великий додаток (скажімо, різні модулі), ви можете розглянути можливість створення декількох проектів, як зазначено вище. У цьому випадку ви можете додати до клавіш класів та класів ресурсів префікс певного модуля. Використовуйте найкращий редактор мов для Visual Studio, щоб об’єднати всі файли в єдиний огляд.

Використання в іншому проекті

Посилання на ваш проект: Клацніть правою кнопкою миші посилання -> Додати посилання -> Prjects \ Solutions.

Використовуйте простір імен у файлі: using MyProject.Language;

Використовуйте це так, як це string someText = Resources.orderGeneralError; робиться у фоновому режимі: Якщо є щось інше, що називається Ресурси, просто введіть у весь простір імен.

Використання в 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>

або якщо ви не хочете визначати використання, просто заповніть весь простір імен АБО ви можете визначити простір імен у /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: Дивовижний навчальний блог

Використання в бібліотеках класів для моделей

Бек-енд використання - це те саме, але лише приклад використання в атрибутах

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; }
    }
}

Якщо у вас є переробник, він автоматично перевірить, чи існує вказана назва ресурсу. Якщо ви віддаєте перевагу безпеці типу, ви можете використовувати шаблони T4 для створення переліку

Використання у WPF.

Звичайно, додайте посилання на ваш простір імен MyProject.Language , ми знаємо, як використовувати його у фоновому режимі.

У XAML, всередині заголовка вікна або 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. Ви можете виконати власну реалізацію (вибрати під час встановлення) або дозволити системі вирішити.

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        SetLanguageDictionary();
    }

    private void SetLanguageDictionary()
    {
        switch (Thread.CurrentThread.CurrentCulture.ToString())
        {
            case "nl-NL":
                MyProject.Language.Resources.Culture = new System.Globalization.CultureInfo("nl-NL");
                break;
            case "en-GB":
                MyProject.Language.Resources.Culture = new System.Globalization.CultureInfo("en-GB");
                break;
            default://default english because there can be so many different system language, we rather fallback on english in this case.
                MyProject.Language.Resources.Culture = new System.Globalization.CultureInfo("en-GB");
                break;
        }
       
    }
}

Використання в UWP

У UWP Microsoft використовує це рішення , тобто вам потрібно буде створити нові файли ресурсів. Крім того, ви не можете повторно використовувати текст, оскільки вони хочуть, щоб ви встановили x:Uidелемент керування в XAML як ключ у ваших ресурсах. І у своїх ресурсах вам потрібно зробити, 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());

Останній рядок потрібен для оновлення інтерфейсу. Поки я все ще працюю над цим проектом, я помітив, що мені потрібно було зробити це 2 рази. Я можу закінчити вибір мови при першому запуску користувача. Але оскільки це розповсюджуватиметься через Магазин Windows, мова, як правило, дорівнює системній.

Потім використовуйте в XAML:

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

Використання його в Angular (конвертувати в JSON)

Зараз частіше зустрічається такий фреймворк, як Angular, у поєднанні з компонентами, тож без cshtml. Переклади зберігаються у файлах json, я не збираюся висвітлювати, як це працює, я б просто настійно рекомендував ngx-translate замість кутового мультиперекладу . Отже, якщо ви хочете перетворити переклади у файл JSON, це досить просто, я використовую скрипт шаблону T4, який перетворює файл ресурсів у файл json. Я рекомендую встановити редактор 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. Щоб поєднати декілька файлів json для використання з ngx-translate , дотримуйтесь інструкцій тут

Використовуйте в Xamarin.Android

Як пояснювалося вище в оновленнях, я використовую той самий метод, що і в Angular / JSON. Але Android використовує файли XML, тому я написав файл T4, який генерує ці файли XML.

Шлях: 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 і змініть папку в наведеному вище коді.

Отже, тепер ви можете використовувати один єдиний файл ресурсів для всіх своїх проектів. Це дозволяє дуже легко експортувати все в документ excl, і нехай хтось перекладе його та імпортує знову.

Особлива подяка цьому чудовому розширенню VS, яке чудово працює з resxфайлами. Подумайте про те , щоб пожертвувати йому за його чудову роботу (я не маю до цього нічого спільного, я просто люблю продовження).


1. як додати більше мов після розгортання ?, додавши більше ресурсу до Mylanguage, перекомпілювати та перерозподілити? (2) Чи є яка-небудь IDE або інструмент, який ви використовували для перекладу (у мене понад 40 форм у winform), чи можете ви поділитися? (3) Я спробував, і він не отримав перекладу, коли я змінив культуру на арабську, я створу запитання і повідомлю вас
Сміт

5
1: Просто продублюйте Resources.xx.resx і змініть xx, і скрізь, де я маю оператори switch, додайте мову. 2 Я використовую розширення ResxManager (від TomEnglert), його можна встановити за допомогою Інструменти -> Розширення, приємний спосіб мати мови поруч, але фактичний переклад робиться кимось іншим (легкий експорт та імпорт до / з Excel за допомогою ResxManager). 3. Зіткнувся з цим останнім разом, додавши також один, перевірте всі файли, перелічені вище, але деякі точки зупинки. Однак я не використовував це в WinForms.
CularBytes 01.03.18

13
Чи можу я проголосувати власну відповідь? Мені просто довелося тупо перевірити власну відповідь, щоб виправити помилку переключення між мовами в WPF -.-
CularBytes

1
@TiagoBrenck Привіт, лише в цій конкретній ситуації, якщо англійською мовою є вашою мовою за замовчуванням, ви можете створити файл resources.en-gb.resx і додати туди 1% змін. За замовчуванням, якщо вибрано мову en-gb, а слова не перекладено, вона використовує мову за замовчуванням (resources.resx).
CularBytes

1
Як ви структурували ключі файлу ресурсу? Оскільки я бачу, що ви використовуєте лише один файл ресурсу, і, на вашу думку, у вас є величезна програма, як ви розділили ключі? Щось на зразок "Feature.MyMessage", або "Area.Feature.MyMessage"
Франческо Вентуріні

21

Я бачив проекти, реалізовані з використанням різних підходів, кожен із яких має свої переваги та недоліки.

  • Один зробив це у файлі конфігурації (не мій улюблений)
  • Один робив це за допомогою бази даних - це спрацювало досить добре, але було болем у тому, що ви знаєте, що слід підтримувати.
  • Один використовував файли ресурсів, як ви пропонуєте, і я повинен сказати, що це був мій улюблений підхід.
  • Найпростіший зробив це, використовуючи файл включення, повний рядків - негарно.

Я б сказав, що вибраний вами метод ресурсів має багато сенсу. Також було б цікаво побачити відповіді інших людей, оскільки я часто задаюся питанням, чи є кращий спосіб робити подібні речі. Я бачив численні ресурси, які всі вказують на метод використання ресурсів, включаючи один тут, на SO .


5

Я не думаю, що існує "найкращий спосіб". Це справді буде залежати від технологій та типу додатка, який ви створюєте.

Webapps може зберігати інформацію в базі даних, як пропонують інші плакати, але я рекомендую використовувати окремі файли ресурсів. Тобто файли ресурсів відокремлені від вашого джерела . Окремі файли ресурсів зменшують суперечки щодо тих самих файлів, і в міру зростання проекту ви можете виявити, що локалізація здійснюватиметься окремо від бізнес-логіки. (Програмісти та перекладачі).

Гуру Microsoft WinForm та WPF рекомендують використовувати окремі збірки ресурсів, налаштовані для кожної мови.

Здатність WPF розмірювати елементи інтерфейсу користувача до вмісту зменшує необхідну роботу з макетуванням, наприклад: (японські слова набагато коротші за англійські).

Якщо ви розглядаєте WPF: Пропоную прочитати цю статтю msdn. Щоб бути правдивим, я знайшов інструменти локалізації WPF: msbuild, locbaml (і, можливо, електронну таблицю Excel), нудно використовувати, але це працює.

Щось лише трохи пов’язане: типовою проблемою, з якою я стикаюся, є інтеграція застарілих систем, які надсилають повідомлення про помилки (зазвичай англійською мовою), а не коди помилок. Це змушує або змінити застарілі системи, або зіставити серверні рядки з моїми власними кодами помилок, а потім із локалізованими рядками ... yech. Коди помилок є локалізацією друг


4

База даних +1

Форми у вашому додатку можуть навіть перекласти себе на льоту, якщо внести виправлення в базу даних.

Ми використовували систему, де всі елементи керування були зіставлені у файлі XML (по одному на форму) з ідентифікаторами мовних ресурсів, але всі ідентифікатори були в базі даних.

В основному, замість того, щоб кожен елемент управління містив ідентифікатор (реалізуючи інтерфейс або використовуючи властивість тегу у VB6), ми використали той факт, що в .NET дерево управління було легко виявити за допомогою відображення. Процес, коли форма завантажується, створюватиме XML-файл, якщо він відсутній. XML-файл мав би зіставити елементи управління з їх ідентифікаторами ресурсів, тому це просто потрібно було заповнити та відобразити в базі даних. Це означало, що немає необхідності змінювати скомпільований двійковий файл, якщо щось не було позначене тегом, або якщо його потрібно було розділити на інший ідентифікатор (деякі слова англійською мовою, які можуть використовуватися як іменники, так і дієслова, можливо, потребуватимуть перекладу на два різні слова у словнику і не використовуватиметься повторно, але ви можете не виявити цього під час початкового призначення ідентифікаторів).

Єдине, де додаток більше залучається, це коли використовується фаза з точками вставки.

Програмне забезпечення для перекладу баз даних було вашим основним екраном обслуговування CRUD з різними параметрами робочого циклу для полегшення перегляду відсутніх перекладів тощо.


Мені подобається ваш метод, чи можете ви сказати мені, як файл XML генерується, а потім відображається у базі даних?
Сміт

У Form_Load або будь-якому іншому функція перекладу була викликана в екземплярі форми. Завантажено файл XML для цієї форми. Якщо його не було, він був створений. У мене немає схеми, яка використовується, але в основному вона відображала ім'я елемента управління у формі на ідентифікатор перекладу. Отже, будь-який елемент керування на формі, якої не було у файлі XML, отримає запис без ідентифікатора перекладу. Оскільки їх створюють на вимогу, ви можете просто створити форму, запустити програму, яка створюватиме або оновлюватиме файл XML для відсутніх елементів керування. Потім заповніть ідентифікатори перекладу для елементів.
Кейд Ру

4

Я шукав і знайшов:

Якщо ви використовуєте WPF або Silverlight, ваш підхід може використовувати WPF LocalizationExtension з багатьох причин.

ІТ з відкритим кодом БЕЗКОШТОВНО (і залишатиметься безкоштовним) знаходиться у справжньому стабільному стані

У програмі 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 підхід може бути однаковим.

Щасти!


2

Я б запропонував кілька файлів ресурсів. Це не повинно бути так важко налаштувати. Насправді я нещодавно відповів на подібне запитання щодо встановлення глобальних мовних файлів ресурсів у поєднанні з файлами ресурсів мови мови.

Локалізація у Visual Studio 2008

Я вважаю, що найкращий підхід принаймні для розробки WinForm.


Недоліком ресурсів є те, що вам потрібно перезапустити систему, щоб переключити мови. Це, мабуть, прийнятно для більшості, але це мій домашній улюбленець ...
Роман Старков

2

Ви можете використовувати комерційні інструменти, такі як Sisulizer . Це створить супутникову збірку для кожної мови. Єдине, на що слід звернути увагу, це не затушувати імена класів форм (якщо ви використовуєте obfuscator).


0

Більшість проектів із відкритим кодом використовують для цього GetText . Я не знаю, як і чи використовувався він коли-небудь у проекті .Net раніше.


0

Ми використовуємо спеціального постачальника для багатомовної підтримки і розміщуємо всі тексти в таблиці бази даних. Це працює добре, за винятком того, що ми іноді стикаємося з проблемами кешування під час оновлення текстів у базі даних без оновлення веб-програми.


0

Стандартні файли ресурсів простіші. Однак якщо у вас є дані, що залежать від мови, такі як таблиці підстановки, вам доведеться керувати двома наборами ресурсів.

Я цього не робив, але у своєму наступному проекті я застосував би постачальника ресурсів бази даних. Я знайшов, як це зробити на MSDN:

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

Я також знайшов цю реалізацію:

Постачальник DBResource

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.