Verwenden Sie ein separates Projekt mit Ressourcen
Ich kann dies aus unserer Erfahrung mit einer aktuellen Lösung mit 12 24 Projekten, die API, MVC, Projektbibliotheken (Kernfunktionen), WPF, UWP und Xamarin umfasst, beurteilen. Es lohnt sich, diesen langen Beitrag zu lesen, da ich denke, dass dies der beste Weg ist, dies zu tun. Mit Hilfe von VS-Tools leicht exportierbar und importierbar, um an Übersetzungsbüros gesendet oder von anderen Personen überprüft zu werden.
EDIT 02/2018: Die Konvertierung in eine .NET Standard-Bibliothek ist immer noch stark und ermöglicht die Verwendung sogar in .NET Framework und NET Core. Ich habe einen zusätzlichen Abschnitt zum Konvertieren in JSON hinzugefügt, damit beispielsweise Angular ihn verwenden kann.
EDIT 2019: Mit Xamarin funktioniert dies weiterhin auf allen Plattformen. ZB empfiehlt Xamarin.Forms, auch Resx-Dateien zu verwenden. (Ich habe noch keine App in Xamarin.Forms entwickelt, aber die Dokumentation, die für den Einstieg viel zu detailliert ist, behandelt sie: Xamarin.Forms-Dokumentation ). Genau wie beim Konvertieren in JSON können wir es auch in eine XML-Datei für Xamarin.Android konvertieren.
EDIT 2019 (2): Beim Upgrade von WPF auf UWP habe ich festgestellt .resw
, dass sie in UWP lieber einen anderen Dateityp verwenden , der inhaltlich identisch ist, aber unterschiedlich verwendet wird. Ich habe einen anderen Weg gefunden, der meiner Meinung nach besser funktioniert als die Standardlösung .
EDIT 2020: Einige Vorschläge für größere (Modulair-) Projekte wurden aktualisiert, für die möglicherweise mehrsprachige Projekte erforderlich sind.
Also, lasst uns loslegen.
Profis
- Fast überall stark getippt.
- In WPF müssen Sie sich nicht damit befassen
ResourceDirectories
.
- Unterstützt für ASP.NET, Klassenbibliotheken, WPF, Xamarin, .NET Core, .NET Standard, soweit ich getestet habe.
- Es werden keine zusätzlichen Bibliotheken von Drittanbietern benötigt.
- Unterstützt Kultur-Fallback: en-US -> en.
- Nicht nur Back-End, funktioniert auch in XAML für WPF und Xamarin.Forms, in .cshtml für MVC.
- Manipulieren Sie die Sprache einfach, indem Sie die ändern
Thread.CurrentThread.CurrentCulture
- Suchmaschinen können in verschiedenen Sprachen crawlen und Benutzer können sprachspezifische URLs senden oder speichern.
Con's
- WPF XAML ist manchmal fehlerhaft, neu hinzugefügte Zeichenfolgen werden nicht direkt angezeigt. Rebuild ist das temporäre Update (vs2015).
- UWP XAML zeigt keine Intellisense-Vorschläge an und zeigt den Text beim Entwerfen nicht an.
- Sag mir.
Installieren
Erstellen Sie ein Sprachprojekt in Ihrer Lösung und geben Sie ihm einen Namen wie MyProject.Language . Fügen Sie einen Ordner mit dem Namen Ressourcen hinzu, und erstellen Sie in diesem Ordner zwei Ressourcendateien (.resx). Eine heißt Resources.resx und eine andere heißt Resources.en.resx (oder .en-GB.resx für bestimmte). In meiner Implementierung habe ich die NL-Sprache (Niederländisch) als Standardsprache, sodass diese in meiner ersten Datei und Englisch in meiner zweiten Datei enthalten ist.
Das Setup sollte folgendermaßen aussehen:
Die Eigenschaften für Resources.resx müssen sein:
Stellen Sie sicher, dass der benutzerdefinierte Tool-Namespace auf Ihren Projekt-Namespace festgelegt ist. Grund dafür ist, dass Sie in WPF nicht auf Resources
XAML verweisen können .
Setzen Sie in der Ressourcendatei den Zugriffsmodifikator auf Öffentlich:
Wenn Sie eine so große Anwendung haben (sagen wir verschiedene Module), können Sie mehrere Projekte wie oben erstellen. In diesem Fall können Sie Ihren Schlüsseln und Ressourcenklassen das jeweilige Modul voranstellen. Verwenden Sie den besten Spracheditor für Visual Studio, um alle Dateien in einer einzigen Übersicht zu kombinieren.
Verwendung in einem anderen Projekt
Verweis auf Ihr Projekt: Klicken Sie mit der rechten Maustaste auf Verweise -> Verweis hinzufügen -> Projekte \ Lösungen.
Verwenden Sie den Namespace in einer Datei: using MyProject.Language;
Verwenden Sie es wie string someText = Resources.orderGeneralError;
folgt im Backend :
Wenn es etwas anderes gibt, das als Ressourcen bezeichnet wird, fügen Sie einfach den gesamten Namespace ein.
Verwendung in MVC
In MVC können Sie die Sprache beliebig einstellen, aber ich habe parametrisierte URLs verwendet, die wie folgt eingerichtet werden können:
RouteConfig.cs
Unter den anderen Zuordnungen
routes.MapRoute(
name: "Locolized",
url: "{lang}/{controller}/{action}/{id}",
constraints: new { lang = @"(\w{2})|(\w{2}-\w{2})" },
defaults: new { controller = "shop", action = "index", id = UrlParameter.Optional }
);
FilterConfig.cs (muss möglicherweise hinzugefügt werden, wenn ja, fügen Sie FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
der Application_start()
Methode in hinzuGlobal.asax
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new ErrorHandler.AiHandleErrorAttribute());
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 legt nur die Kulturinformationen fest.
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;
info.DateTimeFormat.DateSeparator = "/";
info.DateTimeFormat.ShortDatePattern = "dd/MM/yyyy";
Thread.CurrentThread.CurrentUICulture = info;
Thread.CurrentThread.CurrentCulture = info;
}
catch (Exception)
{
}
}
Verwendung in .cshtml
@using MyProject.Language;
<h3>@Resources.w_home_header</h3>
oder wenn Sie keine Verwendungen definieren möchten, füllen Sie einfach den gesamten Namespace aus ODER Sie können den Namespace unter /Views/web.config definieren:
<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>
Dieses Tutorial zur Quell-Implementierung von mvc: Awesome tutorial blog
Verwendung in Klassenbibliotheken für Modelle
Die Verwendung im Back-End ist dieselbe, jedoch nur ein Beispiel für die Verwendung in Attributen
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; }
}
}
Wenn Sie eine Umgestaltung vorgenommen haben, wird automatisch überprüft, ob der angegebene Ressourcenname vorhanden ist. Wenn Sie die Typensicherheit bevorzugen, können Sie T4-Vorlagen verwenden, um eine Aufzählung zu generieren
Verwendung in WPF.
Natürlich fügen Sie einen Verweis auf Ihren MyProject.Language- Namespace hinzu. Wir wissen, wie man ihn im Back-End verwendet.
Fügen Sie in XAML in der Kopfzeile eines Fensters oder UserControls eine Namespace-Referenz hinzu, die lang
wie folgt heißt :
<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">
Dann in einem Etikett:
<Label x:Name="lblHeader" Content="{x:Static lang:Resources.w_home_header}" TextBlock.FontSize="20" HorizontalAlignment="Center"/>
Da es stark typisiert ist, sind Sie sicher, dass die Ressourcenzeichenfolge vorhanden ist. Möglicherweise müssen Sie das Projekt manchmal während des Setups neu kompilieren. WPF ist manchmal fehlerhaft mit neuen Namespaces.
Eine weitere Sache für WPF, stellen Sie die Sprache innerhalb der App.xaml.cs
. Sie können Ihre eigene Implementierung durchführen (während der Installation auswählen) oder das System entscheiden lassen.
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:
MyProject.Language.Resources.Culture = new System.Globalization.CultureInfo("en-GB");
break;
}
}
}
Verwendung in UWP
In UWP verwendet Microsoft diese Lösung , dh Sie müssen neue Ressourcendateien erstellen. Außerdem können Sie den Text auch nicht wiederverwenden, da Sie x:Uid
das Steuerelement in XAML auf einen Schlüssel in Ihren Ressourcen setzen sollen. Und in Ihren Ressourcen müssen Sie tun Example.Text
, um TextBlock
den Text von a zu füllen . Diese Lösung hat mir überhaupt nicht gefallen, weil ich meine Ressourcendateien wiederverwenden möchte. Schließlich fand ich die folgende Lösung. Ich habe das heute (26.09.2019) herausgefunden, sodass ich möglicherweise mit etwas anderem zurückkomme, wenn sich herausstellt, dass dies nicht wie gewünscht funktioniert.
Fügen Sie dies Ihrem Projekt hinzu:
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);
}
}
Fügen Sie dies App.xaml.cs
im Konstruktor hinzu:
CustomXamlResourceLoader.Current = new MyXamlResourceLoader();
Wo immer Sie möchten, ändern Sie die Sprache in Ihrer App:
ApplicationLanguages.PrimaryLanguageOverride = "nl";
Frame.Navigate(this.GetType());
Die letzte Zeile wird benötigt, um die Benutzeroberfläche zu aktualisieren. Während ich noch an diesem Projekt arbeite, habe ich festgestellt, dass ich dies zweimal tun muss. Möglicherweise wird beim ersten Start des Benutzers eine Sprachauswahl angezeigt. Da dies jedoch über den Windows Store verteilt wird, entspricht die Sprache normalerweise der Systemsprache.
Dann verwenden Sie in XAML:
<TextBlock Text="{CustomResource ExampleResourceKey}"></TextBlock>
Verwendung in Angular (Konvertierung in JSON)
Heutzutage ist es üblicher, ein Framework wie Angular in Kombination mit Komponenten zu haben, also ohne cshtml. Übersetzungen werden in JSON-Dateien gespeichert. Ich werde nicht darauf eingehen, wie das funktioniert. Ich würde ngx-translate anstelle der eckigen Mehrfachübersetzung nur empfehlen . Wenn Sie also Übersetzungen in eine JSON-Datei konvertieren möchten, ist dies ziemlich einfach. Ich verwende ein T4-Vorlagenskript, das die Ressourcendatei in eine JSON-Datei konvertiert. Ich empfehle, den T4-Editor zu installieren , um die Syntax zu lesen und korrekt zu verwenden, da Sie einige Änderungen vornehmen müssen.
Nur eines ist zu beachten: Es ist nicht möglich, die Daten zu generieren, zu kopieren, zu bereinigen und für eine andere Sprache zu generieren. Sie müssen also den folgenden Code so oft kopieren, wie Sie Sprachen haben, und den Eintrag vor '// Sprache hier auswählen' ändern. Derzeit ist keine Zeit, dies zu beheben, wird aber wahrscheinlich später aktualisiert (falls interessiert).
Pfad: 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";
var fileResultPath = Path.Combine(Path.GetDirectoryName(this.Host.ResolvePath("")), "MyProject.Language", fileResultName);
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 };
string[] fileNamesDest = new string[] {fileNameDestEn };
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);
}
#>
Wenn Sie eine Modulair-Anwendung haben und meinem Vorschlag gefolgt sind, mehrsprachige Projekte zu erstellen, müssen Sie für jedes eine T4-Datei erstellen. Stellen Sie sicher, dass die JSON-Dateien logisch definiert sind, es muss nicht sein en.json
, es kann auch sein example-en.json
. Befolgen Sie die Anweisungen hier, um mehrere JSON- Dateien für die Verwendung mit ngx-translate zu kombinieren
Verwendung in Xamarin.Android
Wie oben in den Updates erläutert, verwende ich dieselbe Methode wie bei Angular / JSON. Da Android jedoch XML-Dateien verwendet, habe ich eine T4-Datei geschrieben, die diese XML-Dateien generiert.
Pfad: 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;
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("&", "&");
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 funktioniert mit values-xx
Ordnern, daher ist oben für Englisch im values-en
Ordner. Sie müssen aber auch einen Standard generieren, der in den values
Ordner verschoben wird. Kopieren Sie einfach die obige T4-Vorlage und ändern Sie den Ordner im obigen Code.
Jetzt können Sie eine einzige Ressourcendatei für alle Ihre Projekte verwenden. Dies macht es sehr einfach, alles in ein Ausschlussdokument zu exportieren und es von jemandem übersetzen und erneut importieren zu lassen.
Besonderer Dank geht an diese erstaunliche VS-Erweiterung, die hervorragend mit resx
Dateien funktioniert . Betrachten Sie spenden ihm für seine großartige Arbeit (Ich habe nichts damit zu tun, ich liebe einfach die Erweiterung).
Ich habe Projekte gesehen, die mit verschiedenen Ansätzen umgesetzt wurden, von denen jeder seine Vor- und Nachteile hat.
Ich würde sagen, die von Ihnen gewählte Ressourcenmethode ist sehr sinnvoll. Es wäre interessant, auch die Antworten anderer Leute zu sehen, da ich mich oft frage, ob es einen besseren Weg gibt, solche Dinge zu tun. Ich habe zahlreiche Ressourcen gesehen, die alle auf die Methode der Verwendung von Ressourcen verweisen, einschließlich einer hier auf SO .
quelle
Ich glaube nicht, dass es einen "besten Weg" gibt. Dies hängt wirklich von den Technologien und der Art der Anwendung ab, die Sie erstellen.
Webapps können die Informationen in der Datenbank speichern, wie andere Poster vorgeschlagen haben. Ich empfehle jedoch, separate Ressourcendateien zu verwenden. Das sind Ressourcendateien, die von Ihrer Quelle getrennt sind . Separate Ressourcendateien reduzieren die Konkurrenz für dieselben Dateien, und wenn Ihr Projekt wächst, wird die Lokalisierung möglicherweise getrennt von der Geschäftslogik durchgeführt. (Programmierer und Übersetzer).
Microsoft WinForm- und WPF-Gurus empfehlen die Verwendung separater Ressourcenassemblys, die an jedes Gebietsschema angepasst sind.
Die Fähigkeit von WPF, UI-Elemente an den Inhalt anzupassen, verringert die erforderliche Layoutarbeit, z. B.: (Japanische Wörter sind viel kürzer als englische).
Wenn Sie über WPF nachdenken: Ich schlage vor, diesen MSDN-Artikel zu lesen. Um ehrlich zu sein, fand ich die WPF-Lokalisierungstools: msbuild, locbaml (und möglicherweise eine Excel-Tabelle) mühsam zu verwenden, aber es funktioniert.
Etwas nur geringfügig Verwandtes: Ein häufiges Problem ist die Integration von Legacy-Systemen, die Fehlermeldungen (normalerweise in Englisch) und keine Fehlercodes senden. Dies erzwingt entweder Änderungen an Legacy-Systemen oder die Zuordnung von Backend-Zeichenfolgen zu meinen eigenen Fehlercodes und dann zu lokalisierten Zeichenfolgen ... yech. Fehlercodes sind Freunde der Lokalisierung
quelle
+1 Datenbank
Formulare in Ihrer App können sich sogar im laufenden Betrieb neu übersetzen, wenn Korrekturen an der Datenbank vorgenommen werden.
Wir haben ein System verwendet, bei dem alle Steuerelemente in einer XML-Datei (eines pro Formular) Sprachressourcen-IDs zugeordnet wurden, sich jedoch alle IDs in der Datenbank befanden.
Anstatt dass jedes Steuerelement die ID enthält (Implementierung einer Schnittstelle oder Verwendung der Tag-Eigenschaft in VB6), haben wir im Grunde die Tatsache verwendet, dass in .NET der Steuerelementbaum durch Reflexion leicht erkennbar war. Ein Prozess beim Laden des Formulars erstellt die XML-Datei, wenn sie fehlt. Die XML-Datei ordnete die Steuerelemente ihren Ressourcen-IDs zu, sodass diese lediglich ausgefüllt und der Datenbank zugeordnet werden mussten. Dies bedeutete, dass die kompilierte Binärdatei nicht geändert werden musste, wenn etwas nicht markiert war oder wenn es in eine andere ID aufgeteilt werden musste (einige englische Wörter, die sowohl als Substantive als auch als Verben verwendet werden können, müssen möglicherweise in zwei verschiedene Wörter übersetzt werden im Wörterbuch und nicht wiederverwendet werden, aber Sie werden dies möglicherweise bei der ersten Zuweisung von IDs nicht feststellen).
Die App wird nur dann stärker einbezogen, wenn eine Phase mit Einfügemarken verwendet wird.
Die Datenbankübersetzungssoftware war Ihr grundlegender CRUD-Wartungsbildschirm mit verschiedenen Workflow-Optionen, um das Durchsuchen der fehlenden Übersetzungen usw. zu erleichtern.
quelle
Ich habe gesucht und Folgendes gefunden:
Wenn Sie WPF oder Silverlight verwenden, kann Ihr Ansatz aus vielen Gründen WPF LocalizationExtension verwenden .
Es ist Open Source Es ist KOSTENLOS (und wird kostenlos bleiben) und befindet sich in einem echten stabilen Zustand
In einer Windows-Anwendung können Sie Folgendes tun:
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); } }
Und ich denke auf einer Wep-Seite könnte der Ansatz der gleiche sein.
Viel Glück!
quelle
Ich würde mit den mehreren Ressourcendateien gehen. Es sollte nicht so schwer zu konfigurieren sein. Tatsächlich habe ich kürzlich eine ähnliche Frage zum Festlegen globaler sprachbasierter Ressourcendateien in Verbindung mit Ressourcendateien in Formsprache beantwortet.
Lokalisierung in Visual Studio 2008
Ich würde das zumindest für die WinForm-Entwicklung als den besten Ansatz betrachten.
quelle
Sie können kommerzielle Tools wie Sisulizer verwenden . Es wird eine Satellitenassemblierung für jede Sprache erstellt. Sie sollten nur darauf achten, die Namen der Formularklassen nicht zu verschleiern (wenn Sie den Verschleierer verwenden).
quelle
Die meisten OpenSource-Projekte verwenden zu diesem Zweck GetText . Ich weiß nicht, wie und ob es jemals zuvor in einem .NET-Projekt verwendet wurde.
quelle
Wir verwenden einen benutzerdefinierten Anbieter für die Unterstützung mehrerer Sprachen und fügen alle Texte in eine Datenbanktabelle ein. Es funktioniert gut, außer dass wir manchmal Probleme beim Zwischenspeichern haben, wenn wir Texte in der Datenbank aktualisieren, ohne die Webanwendung zu aktualisieren.
quelle
Standardressourcendateien sind einfacher. Wenn Sie jedoch sprachabhängige Daten wie Nachschlagetabellen haben, müssen Sie zwei Ressourcensätze verwalten.
Ich habe es nicht getan, aber in meinem nächsten Projekt würde ich einen Datenbankressourcenanbieter implementieren. Ich habe auf MSDN herausgefunden, wie es geht:
http://msdn.microsoft.com/en-us/library/aa905797.aspx
Ich habe auch diese Implementierung gefunden:
DBResource-Anbieter
quelle