วิธีใช้การโลคัลไลเซชันใน C #


268

ฉันดูเหมือนจะไม่สามารถแปลภาษาท้องถิ่นให้ทำงานได้

ฉันมีห้องสมุดเรียน ตอนนี้ฉันต้องการสร้างresxไฟล์ในนั้นและคืนค่าบางอย่างตามวัฒนธรรมเธรด

ฉันจะทำสิ่งนั้นได้อย่างไร


PS: ตรวจสอบให้แน่ใจว่าคุณได้ติดตั้งส่วนขยาย Microsoft MAT (
Multkit

คำตอบ:


571
  • เพิ่มไฟล์ทรัพยากรให้กับโครงการของคุณ (คุณสามารถเรียกมันว่า "strings.resx") โดยทำสิ่งต่อไปนี้:
    คลิกขวาที่คุณสมบัติในโครงการเลือกเพิ่ม -> รายการใหม่ ...ในเมนูบริบทจากนั้นในรายการVisual C # รายการที่เลือก"แฟ้มข้อมูล"strings.resxและชื่อ
  • เพิ่มสตริง resouce ในไฟล์ resx และตั้งชื่อที่ดี (ตัวอย่าง: ตั้งชื่อ "Hello" ด้วยและตั้งค่าเป็น "Hello")
  • บันทึกไฟล์ทรัพยากร ( หมายเหตุ:นี่จะเป็นค่าเริ่มต้นไฟล์ทรัพยากรเนื่องจากไม่มีรหัสภาษาสองตัวอักษร)
  • เพิ่มการอ้างอิงถึงโปรแกรมของคุณ: System.ThreadingและSystem.Globalization

เรียกใช้รหัสนี้:

Console.WriteLine(Properties.strings.Hello);

ควรพิมพ์ "Hello"

ตอนนี้เพิ่มไฟล์ทรัพยากรใหม่ชื่อ "strings.fr.resx" (หมายเหตุส่วน "fr" หนึ่งไฟล์นี้จะมีทรัพยากรเป็นภาษาฝรั่งเศส) เพิ่มทรัพยากรสตริงที่มีชื่อเดียวกับใน strings.resx แต่มีค่าเป็นภาษาฝรั่งเศส (Name = "Hello", Value = "Salut") ตอนนี้ถ้าคุณเรียกใช้รหัสต่อไปนี้ก็ควรพิมพ์ Salut:

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

สิ่งที่เกิดขึ้นคือระบบจะค้นหาทรัพยากรสำหรับ "FR-FR" จะไม่พบหนึ่ง (เนื่องจากเราระบุ "fr" ในไฟล์ของคุณ ") จากนั้นจะกลับไปตรวจสอบ" fr "ซึ่งพบ (และใช้)

รหัสต่อไปนี้จะพิมพ์ "Hello":

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

นั่นเป็นเพราะไม่พบทรัพยากร "en-US" ใด ๆ และยังไม่มีทรัพยากร "en" ดังนั้นมันจะถอยกลับไปเป็นค่าเริ่มต้นซึ่งเป็นสิ่งที่เราเพิ่มจากจุดเริ่มต้น

คุณสามารถสร้างไฟล์ที่มีทรัพยากรเฉพาะเจาะจงมากขึ้นหากต้องการ (เช่น strings.fr-FR.resx และ strings.fr-CA.resx สำหรับภาษาฝรั่งเศสในฝรั่งเศสและแคนาดาตามลำดับ) ในแต่ละไฟล์ดังกล่าวคุณจะต้องเพิ่มทรัพยากรสำหรับสตริงเหล่านั้นที่แตกต่างจากทรัพยากรที่มันจะถอยกลับไป ดังนั้นหากข้อความเหมือนกันในฝรั่งเศสและแคนาดาคุณสามารถใส่ไว้ใน strings.fr.resx ในขณะที่สตริงที่แตกต่างกันในภาษาฝรั่งเศสแคนาดาสามารถเข้าไปใน strings.fr-CA.resx


24
คำตอบอาจอ้างอิงถึงระบบท่อประปา "เบื้องหลัง" ที่ Visual Studio ทำที่นี่: ไฟล์ resx.designer.cs ทำให้การทำงานของระบบ Intellisense แอสเซมบลีดาวเทียมที่คอมไพล์ด้วยไลบรารีคลาสที่จำเป็นต้องปรับใช้กับแอสเซมบลีที่คอมไพล์และโครงการในภายหลังใด ๆ ที่ใช้มัน ฯลฯ ... คำตอบนั้นดีและเรียบง่าย แต่มันไม่ช่วยอธิบายว่าสิ่งใดผิดพลาดเช่น คุณไม่ได้ใช้ Visual Studio
เทา

13
+1 โพสต์! แทนที่จะสร้างไฟล์ด้วยตนเองลองใช้ Zeta Resource Editor ( zeta-resource-editor.com/index.html ) ฟรีและช่วยให้คุณทำการแปลได้เร็วกว่าใน VS
Killnine

4
Access Modifierควรตั้งค่าPublicสำหรับคลาสทรัพยากรที่จะสร้าง คลาสไม่จำเป็นใน Properties namespace เป็นตำแหน่งที่คุณวางไฟล์. resx
Andrey Moiseev

3
โปรดทราบว่าใน VS 2017 resx ที่มีการแปลใน winform ไม่ทำงานเนื่องจากข้อผิดพลาด (อย่างน้อยจนถึงรุ่น 15.4) มีจำหน่ายตั๋ว: developercommunity.visualstudio.com/content/problem/63772/…
muccix

4
ในฐานะที่เป็น. NET 4.5 มันเป็นไปได้ที่จะใช้ System.Globalization.CultureInfo.DefaultThreadCurrentCulture แทน Thread.CurrentThread.CurrentUICulture เพื่อให้คุณเปลี่ยนโลแคลสำหรับแอ็พพลิเคชันทั้งหมดแทนเธรดโดยเธรด
GrixM

41

มันค่อนข้างง่ายจริงๆ Strings.resxสร้างแฟ้มทรัพยากรใหม่ตัวอย่างเช่น ตั้งค่าการAccess Modifier Publicใช้เทมเพลตไฟล์ apprioriate ดังนั้น Visual Studio จะสร้างคลาส accessor โดยอัตโนมัติ (ชื่อจะเป็นStringsในกรณีนี้) นี่คือภาษาเริ่มต้นของคุณ

ตอนนี้เมื่อคุณต้องการเพิ่มพูดการแปลภาษาเยอรมันให้เพิ่มไฟล์ resx ที่แปลแล้ว โดยทั่วไปจะเป็นStrings.de.resxในกรณีนี้ Strings.de-AT.resxหากคุณต้องการที่จะเพิ่มการแปลเพิ่มเติมสำหรับพูดออสเตรียนอกจากนี้คุณยังจะต้องสร้าง

ตอนนี้ไปสร้างสตริง - HelloWorldสมมติว่าสตริงที่มีชื่อ ในของคุณStrings.resxเพิ่มสตริงนี้ด้วยค่า "Hello, world!" ในStrings.de.resxเพิ่ม "Hallo, Welt!" และในStrings.de-AT.resxเพิ่ม "Servus, Welt!" แค่นี้แหละ

ตอนนี้คุณมีStringsคลาสที่สร้างขึ้นและมันมีคุณสมบัติที่มีทะเยอทะยานHelloWorldระดับและมีคุณสมบัติที่มีความทะเยอทะยานการรับคุณสมบัตินี้จะโหลด "Servus, Welt!" เมื่อสถานที่ของคุณเป็น de-AT, "Hallo, Welt! เมื่อสถานที่ของคุณเป็นสถานที่อื่น ๆ (รวมถึง de-DE และ de-CH) และ" Hello, World! "เมื่อสถานที่ของคุณเป็นอย่างอื่นถ้าสตริงเป็น หายไปในเวอร์ชันที่แปลแล้วตัวจัดการทรัพยากรจะเดินขึ้นโซ่โดยอัตโนมัติจากผู้เชี่ยวชาญที่มากที่สุดไปจนถึงทรัพยากรที่ไม่เปลี่ยนแปลง

คุณสามารถใช้ResourceManagerคลาสเพื่อควบคุมเพิ่มเติมเกี่ยวกับวิธีการโหลดสิ่งต่างๆ Stringsคลาสที่สร้างขึ้นใช้เช่นกัน


วิธีการตั้งค่าสถานที่?
Matheus Simon

1
@MatheusSimon: คุณไม่จำเป็นต้องทำ ตามค่าเริ่มต้นระบบจะใช้สถานที่ปัจจุบันของผู้ใช้ หากคุณต้องการบังคับให้บางภาษา (เช่นอนุญาตให้ผู้ใช้เปลี่ยนภาษาด้วยตนเอง) คุณต้องตั้งค่า System.Threading.Thread.CurrentCulture และ CurrentUICulture ในแต่ละเธรดก่อนที่จะโหลดทรัพยากรใด ๆ ในครั้งแรก การรีสตาร์ทแอปพลิเคชันสำหรับสิ่งนี้ง่ายกว่าแทนที่จะอัปเดตตอนรันไทม์
OregonGhost

15

นอกจากนี้ @Fredrik Mörkคำตอบที่ยอดเยี่ยมเกี่ยวกับสตริงเพื่อเพิ่มการแปลเป็นภาษาท้องถิ่นให้ทำดังนี้

  • การตั้งค่ารูปแบบคุณสมบัติของ"Localizable"การtrue
  • เปลี่ยนLanguageคุณสมบัติของฟอร์มเป็นภาษาที่คุณต้องการ (จากรายการแบบหล่นลงพร้อมกับพวกเขาทั้งหมดใน)
  • แปลการควบคุมในรูปแบบนั้นและย้ายพวกเขาเกี่ยวกับถ้าจำเป็นต้องเป็น (สควอชประโยคยาวเต็มรูปแบบที่ฝรั่งเศสจริงๆใน!)

แก้ไข: บทความ MSDN นี้เกี่ยวกับ Localizing Windows Formsไม่ใช่ต้นฉบับที่ฉันเชื่อมโยง ... แต่อาจทำให้มีแสงสว่างมากขึ้นถ้าจำเป็น (อันเก่าถูกพรากไป)


บทความ msdn ไม่สามารถใช้ได้อีกต่อไปแทนที่ใด ๆ ?
fuomag9

ไม่แน่ใจ - ฉันเชื่อมโยงสิ่งที่ดีที่สุดที่ฉันสามารถเห็นได้ แต่ฉันจำไม่ได้ว่าบทความนี้เป็นอย่างไรเมื่อ 7 ปีที่แล้ว;)
noelicus

14

คำตอบที่ยอดเยี่ยมโดยF.Mörk แต่ถ้าคุณต้องการอัปเดตการแปลหรือเพิ่มภาษาใหม่เมื่อมีการเปิดตัวแอปพลิเคชันคุณจะต้องติดขัดเพราะคุณจะต้องคอมไพล์ใหม่เพื่อสร้าง resources.dll

นี่เป็นวิธีการรวบรวม dll ทรัพยากรด้วยตนเอง มันใช้เครื่องมือ resgen.exe และ al.exe (ติดตั้งกับ sdk)

สมมติว่าคุณมีไฟล์ทรัพยากร Strings.fr.resx คุณสามารถรวบรวม dll ทรัพยากรด้วยชุดข้อมูลต่อไปนี้:

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

อย่าลืมรักษา namespace ดั้งเดิมไว้ในชื่อไฟล์ (ที่นี่ "WpfRibbonApplication1")


2
ขอบคุณสำหรับความคิดเห็นเกี่ยวกับการรักษา namespace (y) ซึ่ง - ถ้าพลาด - จะไม่สร้างข้อผิดพลาดใด ๆ แต่เพียงแค่เปลี่ยนกลับไปเป็นทรัพยากรทางเลือก
Mosca Pt

11

การแก้ไขและคำตอบของ@Fredrik Mörkอย่างละเอียด

  • เพิ่มstrings.resxไฟล์ทรัพยากรให้กับโครงการของคุณ (หรือชื่อไฟล์อื่น)
  • ตั้งAccess Modifierเป็นPublic(ในstrings.resxแท็บไฟล์ที่เปิด)
  • เพิ่มสายอักขระ resouce ในไฟล์ resx: (ตัวอย่าง: ชื่อHello, ค่าHello)
  • บันทึกไฟล์ทรัพยากร

Visual Studio อัตโนมัติสร้างแต่ละชั้นซึ่งวางอยู่ในstrings strings.Designer.csคลาสอยู่ในเนมสเปซเดียวกันกับที่คุณคาดว่า.csจะวางไฟล์ที่สร้างขึ้นใหม่

รหัสนี้จะพิมพ์เสมอHelloเพราะนี่เป็นทรัพยากรเริ่มต้นและไม่มีทรัพยากรเฉพาะภาษา:

Console.WriteLine(strings.Hello);

ตอนนี้เพิ่มทรัพยากรเฉพาะภาษาใหม่:

  • เพิ่มstrings.fr.resx(สำหรับภาษาฝรั่งเศส)
  • เพิ่มสตริงที่มีชื่อเดียวกันกับก่อนหน้านี้ แต่มีค่าต่างกัน: (ชื่อHelloค่าSalut)

พิมพ์รหัสต่อไปนี้Salut:

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

Thread.CurrentThread.CurrentUICultureสิ่งที่ทรัพยากรถูกใช้ขึ้นอยู่กับ มันถูกตั้งค่าขึ้นอยู่กับการตั้งค่าภาษาของ Windows UI หรือสามารถตั้งค่าด้วยตนเองเหมือนในตัวอย่างนี้ เรียนรู้เพิ่มเติมเกี่ยวกับเรื่องนี้ที่นี่

คุณสามารถเพิ่มทรัพยากรเฉพาะประเทศเหมือนหรือstrings.fr-FR.resxstrings.fr-CA.resx

สตริงที่จะใช้ถูกกำหนดตามลำดับความสำคัญนี้:

  • จากแหล่งข้อมูลเฉพาะของประเทศเช่น strings.fr-CA.resx
  • จากทรัพยากรเฉพาะภาษาเช่น strings.fr.resx
  • จากค่าเริ่มต้น strings.resx

หมายเหตุว่าทรัพยากรเฉพาะภาษาสร้างประกอบดาวเทียม

ยังได้เรียนรู้วิธีการที่CurrentCultureแตกต่างจากที่นี่CurrentUICulture


1

ในกรณีของฉัน

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

ใน AssemblyInfo.cs ทำให้สิ่งต่าง ๆ ทำงานตามปกติ


0

นอกจากคำตอบ@Eric Bole-Feysot :

ด้วยแอสเซมบลีของดาวเทียมคุณสามารถสร้างการแปลตามไฟล์. dll / .exe ทางนี้:

  • ซอร์สโค้ด (โครงการ VS) สามารถแยกออกจากโครงการภาษา
  • การเพิ่มภาษาใหม่ไม่จำเป็นต้องมีการคอมไพล์โครงการใหม่
  • การแปลสามารถทำได้แม้กระทั่งโดยผู้ใช้ปลายทาง

มีเครื่องมือที่รู้จักกันเล็กน้อยที่เรียกว่า LSACreator (ฟรีสำหรับการใช้ที่ไม่ใช่เชิงพาณิชย์หรือตัวเลือกซื้อ) ซึ่งช่วยให้คุณสร้างการแปลตามไฟล์. dll / .exe ในความเป็นจริงภายใน (โครงการภาษา directory) มันจะสร้าง / จัดการภาษาท้องถิ่นรุ่นของแฟ้ม resx และรวบรวมการชุมนุมในลักษณะที่คล้ายกันเป็น@ Eric Bole Feysot-อธิบาย


0

ResourceManager และ. resx ค่อนข้างยุ่ง

คุณสามารถใช้Lexical.Localization ¹ซึ่งอนุญาตให้ฝังค่าเริ่มต้นและค่าเฉพาะของวัฒนธรรมลงในรหัสและสามารถขยายในไฟล์การแปลภายนอกสำหรับวัฒนธรรมที่ละเอียดยิ่งขึ้น (เช่น. json หรือ. 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) );
    }
}

¹ (ฉันเป็นผู้ดูแลห้องสมุดนั้น)


0

โดยทั่วไปคุณใส่การแปลของคุณลงในไฟล์ทรัพยากรเช่น resources.resx

แต่ละวัฒนธรรมที่เฉพาะเจาะจงมีชื่อแตกต่างกันเช่น resources.nl.resx, resources.fr.resx, resources.de.resx, ...

ตอนนี้ส่วนที่สำคัญที่สุดของโซลูชันคือการรักษาการแปลของคุณ ใน Visual Studio ติดตั้งเครื่องมือ Microsoft MAT: Multkit App Toolkit (MAT) ทำงานร่วมกับ winforms, wpf, asp.net (core), uwp, ...

โดยทั่วไปเช่นสำหรับโซลูชัน WPF ในโครงการ WPF

  • ติดตั้งส่วนขยาย Microsoft MAT สำหรับ Visual Studio
  • ใน Solution Explorer ไปที่โครงการของคุณ> คุณสมบัติ> AssemblyInfo.cs
  • เพิ่มใน AssemblyInfo.cs ภาษาเริ่มต้นของคุณเป็นกลาง (ในกรณีของฉันภาษาอังกฤษ): [assembly: System.Resources.NeutralResourcesLanguage("en")]
  • เลือกโครงการของคุณใน Solution Explorer และ Visual Studio จากเมนูด้านบนคลิก "เครื่องมือ"> "เครื่องมือแอปหลายภาษา"> "เปิดใช้งานการเลือก" เพื่อเปิดใช้งาน MAT สำหรับโครงการ
    • ตอนนี้คลิกขวาที่เมาส์ในโครงการใน Solution Explorer เลือก "Multilingual App Toolkit"> "เพิ่มภาษาแปล ... " และเลือกภาษาที่คุณต้องการเพิ่มการแปล เช่นภาษาดัตช์

สิ่งที่คุณจะเห็นคือโฟลเดอร์ใหม่จะถูกสร้างขึ้นเรียกว่า "MultilingualResources" ที่มี....nl.xlfไฟล์

สิ่งเดียวที่คุณต้องทำตอนนี้คือ:

  1. เพิ่มการแปลของคุณไปยังไฟล์เริ่มต้นทรัพยากร. resx (ในกรณีของฉันภาษาอังกฤษ)
  2. แปลโดยการคลิกไฟล์. xlf (ไม่ใช่ไฟล์. resx) เนื่องจากไฟล์. xlf จะสร้าง / อัปเดตไฟล์. resx

(ไฟล์. xlf ควรเปิดด้วย "ตัวแก้ไขหลายภาษา" หากไม่ใช่กรณีนี้ให้คลิกเมาส์ขวาที่ไฟล์. xlf เลือก "เปิดด้วย ... " และเลือก "ตัวแก้ไขหลายภาษา"

มีความสุข! ตอนนี้คุณสามารถดูสิ่งที่ยังไม่ได้แปลส่งออกการแปลใน xlf ไปยัง บริษัท แปลภายนอกนำเข้าอีกครั้งรีไซเคิลการแปลจากโครงการอื่น ๆ ฯลฯ ...

ข้อมูลเพิ่มเติม:

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.