Cách sử dụng bản địa hóa trong C #


268

Tôi dường như không thể có được nội địa hóa để làm việc.

Tôi có một thư viện lớp. Bây giờ tôi muốn tạo các tệp resx trong đó và trả về một số giá trị dựa trên văn hóa luồng.

Làm thế nào tôi có thể làm điều đó?


PS: đảm bảo bạn đã cài đặt tiện ích mở rộng Microsoft MAT (Bộ công cụ ứng dụng đa ngôn ngữ) miễn phí cho phòng thu trực quan ;-)
juFo

Câu trả lời:


571
  • Thêm tệp Tài nguyên vào dự án của bạn (bạn có thể gọi nó là "chuỗi.resx") bằng cách thực hiện như sau:
    Bấm chuột phải vào Thuộc tính trong dự án, chọn Thêm -> Mục mới ... trong menu ngữ cảnh, sau đó trong danh sách Các mục Visual C # chọn "Tài nguyên tệp" và đặt tên cho nó strings.resx.
  • Thêm một chuỗi resouce trong tệp resx và đặt cho nó một tên hay (ví dụ: đặt tên là "Hello" với và đặt cho nó giá trị "Hello")
  • Lưu tệp tài nguyên ( lưu ý: đây sẽ là tệp tài nguyên mặc định , vì nó không có mã ngôn ngữ hai chữ cái)
  • Thêm tài liệu tham khảo cho chương trình của bạn: System.ThreadingSystem.Globalization

Chạy mã này:

Console.WriteLine(Properties.strings.Hello);

Nó sẽ in "Xin chào".

Bây giờ, thêm một tệp tài nguyên mới, được đặt tên là "chuỗi.fr.resx" (lưu ý phần "fr"; phần này sẽ chứa tài nguyên bằng tiếng Pháp). Thêm một tài nguyên chuỗi có cùng tên như trong chuỗi.resx, nhưng với giá trị bằng tiếng Pháp (Name = "Hello", Value = "Salut"). Bây giờ, nếu bạn chạy đoạn mã sau, nó sẽ in Salut:

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("fr-FR");
Console.WriteLine(Properties.strings.Hello);

Điều gì xảy ra là hệ thống sẽ tìm kiếm một tài nguyên cho "fr-FR". Nó sẽ không tìm thấy một (vì chúng tôi đã chỉ định "fr" trong tệp của bạn "). Sau đó, nó sẽ quay lại kiểm tra" fr ", cái mà nó tìm thấy (và sử dụng).

Đoạn mã sau, sẽ in "Xin chào":

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US");
Console.WriteLine(Properties.strings.Hello);

Đó là bởi vì nó không tìm thấy bất kỳ tài nguyên "en-US" nào và cũng không có tài nguyên "en", vì vậy nó sẽ trở về mặc định, đây là tài nguyên mà chúng tôi đã thêm từ đầu.

Bạn có thể tạo các tệp có tài nguyên cụ thể hơn nếu cần (ví dụ: String.fr-FR.resx và String.fr-CA.resx cho tiếng Pháp ở Pháp và Canada). Trong mỗi tệp như vậy, bạn sẽ cần thêm tài nguyên cho các chuỗi khác với tài nguyên mà nó sẽ rơi trở lại. Vì vậy, nếu một văn bản giống nhau ở Pháp và Canada, bạn có thể đặt nó trong chuỗi.fr.resx, trong khi các chuỗi khác nhau trong tiếng Pháp của Canada có thể đi vào chuỗi.fr-CA.resx.


24
Câu trả lời có thể làm tham chiếu đến hệ thống ống nước "hậu trường" đang được Visual Studio thực hiện tại đây: tệp resx.designer.cs, làm cho intellisense hoạt động; các tập hợp vệ tinh được biên dịch với thư viện lớp, cần được triển khai với tập hợp đã biên dịch và bất kỳ dự án nào sau này sử dụng nó, v.v ... Câu trả lời rất hay và đơn giản, nhưng nó không giúp giải thích mọi thứ có thể sai ở đâu, ví dụ như bạn không sử dụng Visual Studio.
Tao

13
+1 bài đăng! Thay vì tạo các tệp theo cách thủ công, hãy thử Zeta Resource Editor ( zeta-resource-editor.com/index.html ). Nó miễn phí và giúp bạn thực hiện các loại bản dịch này NHIỀU nhanh hơn chỉ trong VS.
Killnine

4
Access Modifiernên được đặt Publiccho lớp tài nguyên được tạo. Lớp này không nhất thiết phải có trong không gian tên Thuộc tính, đó là nơi bạn đặt tệp .resx.
Andrey Moiseev

3
Xin lưu ý rằng trong VS 2017 resx với bản địa hóa trong winform không hoạt động do lỗi (ít nhất là cho đến phiên bản 15.4). Một vé có sẵn: developercommunity.visualstudio.com/content/problem/63772/...
muccix

4
Kể từ .NET 4.5, bạn cũng có thể sử dụng System.Globalization.CultInfo.DefaultThreadCienCocate thay vì Thread.CienThread.CảnUICARM để bạn thay đổi ngôn ngữ cho toàn bộ ứng dụng thay vì luồng theo luồng
GrixM

41

Thật ra nó khá đơn giản. Tạo một tệp tài nguyên mới, ví dụ Strings.resx. Đặt Access Modifierthành Public. Sử dụng mẫu tệp apprioriate, do đó Visual Studio sẽ tự động tạo ra một lớp người truy cập (tên này sẽ là Strings, trong trường hợp này). Đây là ngôn ngữ mặc định của bạn.

Bây giờ, khi bạn muốn thêm, giả sử, bản địa hóa tiếng Đức, hãy thêm tệp resx được bản địa hóa. Điều này sẽ được điển hình Strings.de.resxtrong trường hợp này. Nếu bạn muốn thêm nội địa hóa bổ sung cho, giả sử, Áo, bạn cũng sẽ tạo thêm một Strings.de-AT.resx.

Bây giờ hãy tạo một chuỗi - giả sử một chuỗi có tên HelloWorld. Trong của bạn Strings.resx, thêm chuỗi này với giá trị "Xin chào, thế giới!". Trong Strings.de.resx, thêm "Hallo, Welt!". Và trong Strings.de-AT.resx, thêm "Servus, Welt!". Đó là nó cho đến nay.

Bây giờ bạn có Stringslớp được tạo này và nó có một thuộc tính với một getter HelloWorld. Nhận được tài sản này sẽ tải "Servus, Welt!" khi địa điểm của bạn là de-AT, "Hallo, Welt! khi địa điểm của bạn là bất kỳ địa điểm nào khác (bao gồm cả de-DE và de-CH) và" Xin chào, Thế giới! "khi địa điểm của bạn là bất cứ điều gì khác. thiếu trong phiên bản được bản địa hóa, trình quản lý tài nguyên sẽ tự động đi lên chuỗi, từ tài nguyên chuyên biệt nhất đến tài nguyên bất biến.

Bạn có thể sử dụng ResourceManagerlớp để kiểm soát nhiều hơn về cách chính xác bạn đang tải mọi thứ. Lớp được tạo cũng Stringssử dụng nó.


Làm thế nào để thiết lập miền địa phương?
Matheus Simon

1
@MeditusSimon: Bạn không cần. Theo mặc định, ngôn ngữ hiện tại của người dùng được sử dụng. Nếu bạn muốn buộc một ngôn ngữ nhất định (ví dụ: cho phép người dùng thay đổi ngôn ngữ theo cách thủ công), bạn phải đặt System.Threading.Thread.CiverseCocate và CurrentUICARM trong mỗi luồng , có thể trước khi bất kỳ tài nguyên nào được tải lần đầu tiên. Dễ dàng khởi động lại một ứng dụng cho việc này hơn là cập nhật khi chạy.
OregonGhost

15

Ngoài ra, câu trả lời tuyệt vời của @Fredrik Mörk về chuỗi, để thêm nội địa hóa vào biểu mẫu, hãy làm như sau:

  • Đặt hình thức sở hữu 's "Localizable"đểtrue
  • Thay đổi thuộc tính của biểu mẫu thành Languagengôn ngữ bạn muốn (từ trình đơn thả xuống đẹp với tất cả trong đó)
  • Dịch các điều khiển ở dạng đó và di chuyển chúng nếu cần (loại bỏ những câu tiếng Pháp thực sự dài đầy đủ trong!)

Chỉnh sửa: Bài viết MSDN này về Bản địa hóa Windows Forms không phải là bản gốc tôi đã liên kết ... nhưng có thể làm sáng tỏ hơn nếu cần. (cái cũ đã bị lấy đi)


Các bài viết msDN không có sẵn nữa, bất kỳ thay thế?
fuomag9

Không chắc chắn - Tôi đã liên kết bài tốt nhất tôi có thể thấy, nhưng tôi không thể nhớ bài báo đó như thế nào 7 năm trước;)
noelicus

14

Câu trả lời tuyệt vời của F.Mork. Nhưng nếu bạn muốn cập nhật bản dịch hoặc thêm ngôn ngữ mới sau khi ứng dụng được phát hành, bạn sẽ bị mắc kẹt, vì bạn luôn phải biên dịch lại để tạo tài nguyên.dll.

Đây là một giải pháp để tự biên dịch một dll tài nguyên. Nó sử dụng các công cụ resgen.exe và al.exe (được cài đặt với sdk).

Giả sử bạn có tệp tài nguyên String.fr.resx, bạn có thể biên dịch dll tài nguyên với lô sau:

resgen.exe /compile Strings.fr.resx,WpfRibbonApplication1.Strings.fr.resources 
Al.exe /t:lib /embed:WpfRibbonApplication1.Strings.fr.resources /culture:"fr" /out:"WpfRibbonApplication1.resources.dll"
del WpfRibbonApplication1.Strings.fr.resources
pause

Đảm bảo giữ không gian tên gốc trong tên tệp (ở đây "WpfRunkApplication1")


2
Cảm ơn bạn đã nhận xét về việc giữ nguyên không gian tên (y), mà - nếu bị bỏ lỡ - sẽ không tạo ra bất kỳ lỗi nào, mà chỉ đơn giản là trở lại tài nguyên dự phòng.
Mosca Pt

11

Một bản sửa lỗi và xây dựng câu trả lời @Fredrik Mörk .

  • Thêm strings.resxtệp Tài nguyên vào dự án của bạn (hoặc tên tệp khác)
  • Đặt Access Modifierthành Public(trong strings.resxtab tệp đã mở )
  • Thêm một chuỗi resouce trong tệp resx: (ví dụ: tên Hello, giá trị Hello)
  • Lưu tệp tài nguyên

Visual Studio tự động tạo một stringslớp tương ứng , thực sự được đặt trong strings.Designer.cs. Lớp học nằm trong cùng một không gian tên mà bạn mong đợi một lớp mới được tạo.cs tệp sẽ được đặt vào.

Mã này luôn được in Hello, vì đây là tài nguyên mặc định và không có tài nguyên dành riêng cho ngôn ngữ:

Console.WriteLine(strings.Hello);

Bây giờ thêm một tài nguyên ngôn ngữ cụ thể mới:

  • Thêm strings.fr.resx(cho tiếng Pháp)
  • Thêm một chuỗi có cùng tên như trước đây, nhưng giá trị khác nhau: (tên Hello, giá trị Salut)

Các đoạn mã sau in Salut:

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("fr-FR");
Console.WriteLine(strings.Hello);

Tài nguyên nào được sử dụng phụ thuộc vào Thread.CurrentThread.CurrentUICulture. Nó được đặt tùy thuộc vào cài đặt ngôn ngữ UI của Windows hoặc có thể được đặt thủ công như trong ví dụ này. Tìm hiểu thêm về điều này ở đây .

Bạn có thể thêm tài nguyên theo quốc gia cụ thể như strings.fr-FR.resxhoặcstrings.fr-CA.resx .

Chuỗi được sử dụng được xác định theo thứ tự ưu tiên này:

  • Từ tài nguyên cụ thể theo quốc gia như strings.fr-CA.resx
  • Từ tài nguyên dành riêng cho ngôn ngữ như strings.fr.resx
  • Từ mặc định strings.resx

Lưu ý rằng tài nguyên dành riêng cho ngôn ngữ tạo ra các cụm vệ tinh .

Cũng tìm hiểu làm thế nào CurrentCulturekhác nhau từ CurrentUICulture đây .


1

Trong trường hợp của tôi

[assembly: System.Resources.NeutralResourcesLanguage("ru-RU")]

trong hội nghịInfo.cs đã ngăn mọi thứ hoạt động như bình thường.


0

Ngoài @Eric Bole-Feysot câu trả lời :

Nhờ các cụm vệ tinh, bản địa hóa có thể được tạo dựa trên các tập tin / .exe . Cách này:

  • mã nguồn (dự án VS) có thể được tách ra khỏi dự án ngôn ngữ,
  • thêm một ngôn ngữ mới không yêu cầu biên dịch lại dự án,
  • bản dịch có thể được thực hiện ngay cả bởi người dùng cuối.

Có một công cụ ít được biết đến gọi là LSACreator (miễn phí cho sử dụng phi thương mại hoặc tùy chọn mua) cho phép bạn tạo bản địa hóa dựa trên các tập tin / .exe. Trong thực tế, bên trong (trong thư mục của dự án ngôn ngữ), nó tạo / quản lý các phiên bản cục bộ của các tệp resx và biên dịch một tập hợp theo cách tương tự như @Eric Bole-Feysot mô tả.


0

ResourceManager và .resx hơi lộn xộn.

Bạn có thể sử dụng Lexical.Localization cho phép nhúng giá trị mặc định và giá trị văn hóa cụ thể vào mã và được mở rộng trong các tệp bản địa hóa bên ngoài cho các nền văn hóa xa hơn (như .json hoặc .resx).

public class MyClass
{
    /// <summary>
    /// Localization root for this class.
    /// </summary>
    static ILine localization = LineRoot.Global.Type<MyClass>();

    /// <summary>
    /// Localization key "Ok" with a default string, and couple of inlined strings for two cultures.
    /// </summary>
    static ILine ok = localization.Key("Success")
            .Text("Success")
            .fi("Onnistui")
            .sv("Det funkar");

    /// <summary>
    /// Localization key "Error" with a default string, and couple of inlined ones for two cultures.
    /// </summary>
    static ILine error = localization.Key("Error")
            .Format("Error (Code=0x{0:X8})")
            .fi("Virhe (Koodi=0x{0:X8})")
            .sv("Sönder (Kod=0x{0:X8})");

    public void DoOk()
    {
        Console.WriteLine( ok );
    }

    public void DoError()
    {
        Console.WriteLine( error.Value(0x100) );
    }
}

(Tôi đang duy trì thư viện đó)


0

Nói chung, bạn đặt bản dịch của mình trong các tệp tài nguyên, ví dụ resource.resx.

Mỗi nền văn hóa cụ thể có một tên khác nhau, ví dụ: resource.nl.resx, resource.fr.resx, resource.de.resx, khắc

Bây giờ phần quan trọng nhất của một giải pháp là duy trì bản dịch của bạn. Trong Visual Studio cài đặt công cụ Microsoft MAT: Bộ công cụ ứng dụng đa ngôn ngữ (MAT). Hoạt động với winforms, wpf, asp.net (core), uwp, khắc

Nói chung, ví dụ cho một giải pháp WPF, trong dự án WPF

  • Cài đặt tiện ích mở rộng Microsoft MAT cho Visual Studio.
  • Trong Solution Explorer, điều hướng đến Dự án> Thuộc tính> HộiInfo.cs của bạn
  • Thêm vào AssociationInfo.cs ngôn ngữ trung lập, mặc định của bạn (trong trường hợp của tôi là tiếng Anh): [assembly: System.Resources.NeutralResourcesLanguage("en")]
  • Chọn dự án của bạn trong Solution Explorer và trong Visual Studio, từ menu trên cùng, nhấp vào "Công cụ"> "Bộ công cụ ứng dụng đa ngôn ngữ"> "Bật lựa chọn", để bật MAT cho dự án.
    • Bây giờ, nhấp chuột phải vào dự án trong Solution Explorer, chọn "Bộ công cụ ứng dụng đa ngôn ngữ"> "Thêm ngôn ngữ dịch thuật" và chọn ngôn ngữ mà bạn muốn thêm bản dịch. vd: tiếng Hà Lan.

Những gì bạn sẽ thấy là một thư mục mới sẽ được tạo, được gọi là "Đa ngôn ngữ" có chứa một ....nl.xlf tệp.

Điều duy nhất bây giờ bạn phải làm là:

  1. thêm bản dịch của bạn vào tệp resource.resx mặc định của bạn (trong trường hợp của tôi là tiếng Anh)
  2. Dịch bằng cách nhấp vào tệp .xlf (KHÔNG phải tệp .resx) vì các tệp .xlf sẽ tạo / cập nhật các tệp .resx.

(các tệp .xlf sẽ mở bằng "Trình soạn thảo đa ngôn ngữ", nếu không phải như vậy, nhấp chuột phải vào tệp .xlf, chọn "Mở bằng cách" và chọn "Trình soạn thảo đa ngôn ngữ".

Chúc vui vẻ! bây giờ bạn cũng có thể thấy những gì chưa được dịch, xuất bản dịch trong xlf sang các công ty dịch thuật bên ngoài, nhập lại chúng, tái chế các bản dịch từ các dự án khác, v.v ...

Thêm thông tin:

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.