Trong dự án hiện tại của tôi (.NET Windows Forms application) Tôi có yêu cầu các biểu mẫu .NET phải được bản địa hóa nhưng các phần tử bản địa hóa (chỉ là bản dịch chứ không phải hình ảnh hoặc vị trí kiểm soát) nên đến từ cơ sở dữ liệu để cho phép người dùng cuối sửa đổi các thuộc tính kiểm soát được bản địa hóa (chỉ phụ đề/văn bản) như họ muốn. Để giữ cho các nhà phát triển unburdened với các vấn đề nội địa hóa giải pháp tốt nhất cho tôi sẽ chỉ đơn giản là đánh dấu các hình thức như bản địa hóa trong VS thiết kế. Điều này sẽ đặt tất cả các giá trị thuộc tính có thể bản địa hóa trong tệp .resx của biểu mẫu.Nội địa hóa WinForms .NET - thay thế ComponentResourceManager
Bây giờ, sự cố của tôi là cách cung cấp bản dịch từ cơ sở dữ liệu. Thời điểm biểu mẫu được đánh dấu là Bản địa hóa thiết kế biểu mẫu VS sẽ đặt mọi thứ có thể được bản địa hóa là tệp .resx. Nhà thiết kế cũng sẽ sửa đổi phương thức factory.cs InitializeComponent chuẩn để nó khởi tạo ComponentResourceManager và sau đó sử dụng trình quản lý tài nguyên đó để nạp các thuộc tính có thể bản địa hóa của các đối tượng (các điều khiển và các thành phần).
Tôi đã thấy các giải pháp nơi mọi người đã xây dựng phương pháp riêng của họ trong việc áp dụng các thuộc tính được bản địa hóa cho Biểu mẫu và các điều khiển của nó. Tất cả các giải pháp mà tôi đã nhìn thấy thường đun sôi xuống để đệ quy lặp đi lặp lại thông qua các bộ sưu tập điều khiển của mẫu và điều khiển của nó và áp dụng các bản dịch. Thật không may, các bản địa hóa .NET Forms không đơn giản như vậy và điều này không bao gồm tất cả các kịch bản đặc biệt nếu bạn có một số điều khiển bên thứ 3. Ví dụ:
this.navBarControl.OptionsNavPane.ExpandedWidth = ((int)(resources.GetObject("resource.ExpandedWidth")));
//
// radioGroup1
//
resources.ApplyResources(this.radioGroup1, "radioGroup1");
...
this.radioGroup1.Properties.Items.AddRange(new DevExpress.XtraEditors.Controls.RadioGroupItem[] {
new DevExpress.XtraEditors.Controls.RadioGroupItem(resources.GetString("radioGroup1.Properties.Items"), resources.GetString("radioGroup1.Properties.Items1")),
new DevExpress.XtraEditors.Controls.RadioGroupItem(resources.GetString("radioGroup1.Properties.Items2"), resources.GetString("radioGroup1.Properties.Items3"))});
Tất cả các giải pháp tôi thấy không thể dịch được như yêu cầu của các thành phần trên.
Vì VS đã tạo mã cung cấp bản dịch khi cần giải pháp lý tưởng của tôi sẽ bằng cách nào đó thay thế ComponentResourceManager bằng lớp dẫn xuất của chính tôi. Nếu tôi chỉ có thể thay thế các dòng sau trong InitializeComponent:
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
với
System.ComponentModel.ComponentResourceManager resources = new MyComponentResourceManager(typeof(Form1));
sau đó tôi có thể giải quyết tất cả mọi thứ khác mà không có bất kỳ vấn đề.
Thật không may tôi không tìm thấy cách tôi có thể làm điều gì đó tương tự như vậy ở đây tôi đang trên SO hỏi một câu hỏi về cách nó có thể được thực hiện.
P.S. tôi cũng sẽ chấp nhận bất kỳ giải pháp định vị khác mà phù hợp với các yêu cầu: 1. Thay đổi bản dịch nên có thể mà không redeploying ứng dụng 2. Các nhà phát triển không nên chăm sóc về dịch khi tạo các hình thức/user điều khiển
Cảm ơn bạn.
EDIT: Larry cung cấp tham chiếu tuyệt vời cho sách có mã giải quyết một phần vấn đề của tôi. Với sự trợ giúp đó, tôi đã có thể tạo ra thành phần của riêng tôi thay thế ComponentResourceManager mặc định trong phương thức InitializeComponent. Đây là mã cho một thành phần được gọi là Localizer thay thế các ComponentResourceManager với MyResourceManager tùy chỉnh để người khác cũng có thể được hưởng lợi từ nó:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.CodeDom;
using System.ComponentModel.Design;
namespace LocalizationTest
{
[Designer(typeof(LocalizerDesigner))]
[DesignerSerializer(typeof(LocalizerSerializer), typeof(CodeDomSerializer))]
public class Localizer : Component
{
public static void GetResourceManager(Type type, out ComponentResourceManager resourceManager)
{
resourceManager = new MyResourceManager(type);
}
}
public class MyResourceManager : ComponentResourceManager
{
public MyResourceManager(Type type) : base(type)
{
}
}
public class LocalizerSerializer : CodeDomSerializer
{
public override object Deserialize(IDesignerSerializationManager manager, object codeDomObject)
{
CodeDomSerializer baseSerializer = (CodeDomSerializer)
manager.GetSerializer(typeof(Component), typeof(CodeDomSerializer));
return baseSerializer.Deserialize(manager, codeDomObject);
}
public override object Serialize(IDesignerSerializationManager manager, object value)
{
CodeDomSerializer baseSerializer =
(CodeDomSerializer)manager.GetSerializer(typeof(Component), typeof(CodeDomSerializer));
object codeObject = baseSerializer.Serialize(manager, value);
if (codeObject is CodeStatementCollection)
{
CodeStatementCollection statements = (CodeStatementCollection)codeObject;
CodeTypeDeclaration classTypeDeclaration =
(CodeTypeDeclaration)manager.GetService(typeof(CodeTypeDeclaration));
CodeExpression typeofExpression = new CodeTypeOfExpression(classTypeDeclaration.Name);
CodeDirectionExpression outResourceExpression = new CodeDirectionExpression(
FieldDirection.Out, new CodeVariableReferenceExpression("resources"));
CodeExpression rightCodeExpression =
new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("LocalizationTest.Localizer"), "GetResourceManager",
new CodeExpression[] { typeofExpression, outResourceExpression });
statements.Insert(0, new CodeExpressionStatement(rightCodeExpression));
}
return codeObject;
}
}
public class LocalizerDesigner : ComponentDesigner
{
public override void Initialize(IComponent c)
{
base.Initialize(c);
var dh = (IDesignerHost)GetService(typeof(IDesignerHost));
if (dh == null)
return;
var innerListProperty = dh.Container.Components.GetType().GetProperty("InnerList", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.FlattenHierarchy);
var innerList = innerListProperty.GetValue(dh.Container.Components, null) as System.Collections.ArrayList;
if (innerList == null)
return;
if (innerList.IndexOf(c) <= 1)
return;
innerList.Remove(c);
innerList.Insert(0, c);
}
}
}
Tôi đã tìm hiểu thêm về cách Localizer hoạt động tại đây: http://flylib.com/books/en/3.147.1.147/1/ –