รองรับภาษาและวัฒนธรรมอื่น

แอปมีแหล่งข้อมูลที่เฉพาะเจาะจงกับวัฒนธรรมหนึ่งๆ ตัวอย่างเช่น แอปสามารถรวมสตริงเฉพาะวัฒนธรรมที่แปลเป็นภาษา ภาษาของพื้นที่ปัจจุบัน

วิธีที่ดีคือให้ ทรัพยากรเฉพาะวัฒนธรรมที่แยกจากส่วนอื่นๆ ของแอป Android แก้ปัญหา แหล่งข้อมูลเฉพาะภาษาและวัฒนธรรมตามการตั้งค่าภาษาของระบบ คุณ สามารถให้การสนับสนุนสำหรับภาษาต่างๆ โดยใช้ไดเรกทอรีทรัพยากรใน โปรเจ็กต์ Android ของคุณ

คุณสามารถระบุแหล่งข้อมูลที่ปรับแต่งให้เหมาะกับวัฒนธรรมของผู้คนที่ใช้ แอป คุณจะระบุประเภททรัพยากรใดก็ได้ที่ ที่เหมาะสมกับภาษาและวัฒนธรรมของผู้ใช้ ตัวอย่างเช่น พารามิเตอร์ ภาพหน้าจอต่อไปนี้แสดงแอปที่แสดงสตริงและทรัพยากรที่ถอนออกได้ใน ภาษาen_USเริ่มต้นของอุปกรณ์และภาษาสเปน ภาษาes_ES

แอปแสดง
ข้อความและไอคอนแตกต่างกันไปตามภาษาปัจจุบัน

รูปที่ 1 แอปที่ใช้ทรัพยากรต่างกันขึ้นอยู่กับ สถานที่ปัจจุบัน

เมื่อสร้างโปรเจ็กต์โดยใช้ Android SDK เครื่องมือ เครื่องมือจะสร้างไดเรกทอรี res/ ในระดับบนสุดของ ให้กับโครงการ ภายในไดเรกทอรี res/ นี้คือไดเรกทอรีย่อยสำหรับทรัพยากรต่างๆ ประเภทต่างๆ นอกจากนี้ยังมีไฟล์เริ่มต้นอีก 2-3 ไฟล์ เช่น res/values/strings.xml ซึ่งมีค่าสตริงของคุณ

การรองรับภาษาต่างๆ นอกเหนือจากการใช้ทรัพยากรเฉพาะภาษาแล้ว ผู้ใช้บางรายเลือกภาษาที่ใช้สคริปต์แบบขวาไปซ้าย (RTL) เช่น อาหรับหรือฮีบรูสำหรับภาษา UI ผู้ใช้รายอื่นๆ ที่ตั้งค่าภาษาใน UI เป็นภาษาที่ใช้ สคริปต์ LTR เช่น ภาษาอังกฤษ อาจดูหรือสร้างเนื้อหา ในภาษาที่ใช้สคริปต์ RTL เพื่อรองรับผู้ใช้ทั้ง 2 ประเภท แอปของคุณจำเป็นต้องทำสิ่งต่อไปนี้

  • ใช้การจัดวาง UI RTL สำหรับภาษา RTL
  • ตรวจหาและประกาศทิศทางของข้อมูลข้อความที่แสดงภายใน ข้อความที่จัดรูปแบบ โดยทั่วไปแล้ว คุณจะ เรียกเมธอดตามที่อธิบายไว้ใน คู่มือนี้จะอธิบายถึง ทิศทางของข้อมูลข้อความให้กับคุณ

สร้างไดเรกทอรีภาษาและไฟล์ทรัพยากร

หากต้องการเพิ่มการรองรับภาษาเพิ่มเติม ให้สร้างไดเรกทอรีเพิ่มเติมภายใน res/ ชื่อไดเรกทอรีแต่ละรายการต้องเป็นไปตามรูปแบบต่อไปนี้

<resource type>-b+<language code>[+<country code>]

เช่น values-b+es/ มีสตริง ทรัพยากรสำหรับภาษาที่มีรหัสภาษา es ในทำนองเดียวกัน mipmap-b+es+ES/ มีไอคอนสำหรับภาษาที่มี es รหัสภาษาและรหัสประเทศ ES

Android โหลดทรัพยากรที่เหมาะสมตามการตั้งค่าภาษาของ อุปกรณ์ในระหว่างรันไทม์ สำหรับข้อมูลเพิ่มเติม โปรดดู ระบุแหล่งข้อมูลอื่น

หลังจากที่คุณตัดสินใจเลือกภาษาที่จะรองรับแล้ว ให้สร้างไดเรกทอรีย่อยของทรัพยากรและ เช่น

MyProject/
    res/
       values/
           strings.xml
       values-b+es/
           strings.xml
       mipmap/
           country_flag.png
       mipmap-b+es+ES/
           country_flag.png

เติมข้อมูลไฟล์ทรัพยากรด้วยทรัพยากรที่แปลแล้ว ต่อไปนี้เป็นตัวอย่างของไฟล์ทรัพยากรรูปภาพและสตริงที่แปลแล้ว

สตริงภาษาอังกฤษ (ภาษาเริ่มต้น) ใน /values/strings.xml:

<resources>
    <string name="hello_world">Hello World!</string>
</resources>

สตริงภาษาสเปน (ภาษา es ภาษา) ใน /values-b+es/strings.xml:

<resources>
    <string name="hello_world">¡Hola Mundo!</string>
</resources>

ไอคอนธงชาติสหรัฐอเมริกา (ภาษาเริ่มต้น) ใน /mipmap/country_flag.png:

ไอคอนธงของ
สหรัฐอเมริกา

รูปที่ 2 ไอคอนที่ใช้สำหรับภาษาเริ่มต้น (en_US)

ไอคอนธงชาติสเปน (ภาษาes_ES) ใน /mipmap-b+es+ES/country_flag.png:

ไอคอนธงของ
สเปน

รูปที่ 3 ไอคอนที่ใช้สำหรับภาษา es_ES

หมายเหตุ: คุณสามารถใช้ตัวระบุการกำหนดค่า เช่น ตัวระบุสถานที่ ในทรัพยากรทุกประเภท ตัวอย่างเช่น คุณอาจต้องการ ให้เวอร์ชันแปลของบิตแมปที่ถอนออกได้ ดูข้อมูลเพิ่มเติมได้ที่แปลแอป

ใช้แหล่งข้อมูลในแอป

อ้างอิงทรัพยากรในซอร์สโค้ดและไฟล์ XML อื่นๆ โดยใช้ แอตทริบิวต์ name ของทรัพยากรแต่ละรายการ R.<resource type>.<resource name> มีให้เลือกหลากหลาย ของเมธอดที่ยอมรับทรัพยากร ด้วยวิธีนี้ ดังที่แสดงในตัวอย่างต่อไปนี้:

Kotlin

// Get a string resource
val hello = resources.getString(R.string.hello_world)

// Or supply a string resource to a method that requires a string
TextView(this).apply {
    setText(R.string.hello_world)
}

Java

// Get a string resource
String hello = getResources().getString(R.string.hello_world);

// Or supply a string resource to a method that requires a string
TextView textView = new TextView(this);
textView.setText(R.string.hello_world);

ในไฟล์ XML คุณสามารถอ้างอิงทรัพยากรด้วยไวยากรณ์ได้ @<resource type>/<resource name> เมื่อใดก็ตามที่ XML จะยอมรับค่าที่เข้ากันได้ ดังที่แสดงในตัวอย่างต่อไปนี้

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@mipmap/country_flag" />

หมายเหตุ: เพื่อให้มั่นใจว่าการตั้งค่าภาษาของผู้ใช้จะได้รับการจัดลําดับความสําคัญ ให้ระบุภาษาที่แอปของคุณรองรับโดยใช้พร็อพเพอร์ตี้ resConfigs ให้ถูกต้อง สำหรับ ข้อมูลเพิ่มเติม โปรดดู ระบุภาษาที่แอปของคุณรองรับ

จัดรูปแบบข้อความในข้อความ

หนึ่งในงานที่พบบ่อยที่สุดในแอปคือการจัดรูปแบบข้อความ ข้อความที่แปลแล้ว ที่มีการจัดรูปแบบด้วยการแทรกข้อความและข้อมูลตัวเลขลงในตำแหน่งที่เหมาะสม แต่น่าเสียดายที่เมื่อจัดการกับข้อมูล RTL UI หรือ RTL การจัดรูปแบบอย่างง่ายสามารถ แสดงผลเป็นข้อความที่ไม่ถูกต้องหรือไม่สามารถอ่านได้

ภาษาต่างๆ เช่น อาหรับ ฮิบรู เปอร์เซีย และอูรดู จะใช้เป็น RTL อย่างไรก็ตาม องค์ประกอบบางอย่าง เช่น ตัวเลข และองค์ประกอบที่ฝัง ข้อความ LTR จะเขียนเป็น LTR ภายในข้อความ RTL ภาษาที่ใช้ตัวอักษร LTR ซึ่งรวมถึงภาษาอังกฤษจะเป็นแบบ 2 ทิศทางเช่นกัน เนื่องจากอาจมีสคริปต์ RTL แบบฝังซึ่งต้องแสดง RTL

แอปมักสร้างอินสแตนซ์ของข้อความที่อยู่ฝั่งตรงข้ามที่ฝังอยู่ประเภทนี้ เช่น ด้วยการแทรกข้อมูลที่เป็นข้อความ และทิศทางของข้อความที่กำหนดเองในข้อความที่แปลแล้ว การผสมเส้นทางนี้มักไม่รวมการบอกตำแหน่งที่ชัดเจน ข้อความที่มีทิศทางตรงกันข้ามจะเริ่มต้นและสิ้นสุด ดังนั้นแอปจึงสร้างขึ้น อาจทำให้ผู้ใช้ได้รับประสบการณ์ที่ไม่ดี

แม้ว่าโดยทั่วไป การจัดการข้อความสองทิศทางที่เป็นค่าเริ่มต้นของระบบ ข้อความตามที่คาดไว้ ข้อความอาจแสดงผลไม่ถูกต้องเมื่อแอปของคุณ จะแทรกลงในข้อความที่แปลแล้ว ต่อไปนี้เป็นตัวอย่างสถานการณ์ ตำแหน่งที่ข้อความมีแนวโน้มที่จะปรากฏไม่ถูกต้อง:

  • ข้อความที่แทรกที่จุดเริ่มต้นของข้อความ:

    PERSON_NAME กำลังโทรหาคุณ

  • ข้อความที่ขึ้นต้นด้วยตัวเลข เช่น ที่อยู่หรือหมายเลขโทรศัพท์

    987 654-3210

  • ข้อความที่ขึ้นต้นด้วยเครื่องหมายวรรคตอน เช่น หมายเลขโทรศัพท์

    +19876543210

  • ข้อความที่ลงท้ายด้วยเครื่องหมายวรรคตอน:

    แน่ใจไหม

  • ข้อความที่มีทั้ง 2 ทิศทางอยู่แล้ว

    คำว่า พิพิธภัณฑ์เกี่ยวกับการ รูปแบบนี้เริ่มต้น คือภาษาฮีบรู แปลว่ากล้วย

ตัวอย่าง

สมมติว่าบางครั้งแอปจำเป็นต้องแสดงข้อความ " คุณหมายถึง %s?" โดยมีการแทรกที่อยู่แทนที่ %s ขณะรันไทม์ แอปรองรับภาษา UI ที่แตกต่างกัน ดังนั้นข้อความจะมาจากภาษาเฉพาะ และใช้ทิศทาง RTL เมื่ออุปกรณ์ตั้งค่าเป็น RTL เช่น สำหรับภาษาฮีบรู UI ข้อความจะปรากฏดังนี้

NEWLINEホテ ลบประวัติโดยไปที่ %s?

แต่ที่อยู่ที่แนะนำอาจมาจากฐานข้อมูลที่ไม่มีข้อความ ในภาษาของประเทศนั้นๆ ตัวอย่างเช่น หากที่อยู่เป็นของสถานที่ ในรัฐแคลิฟอร์เนีย ปรากฏอยู่ในฐานข้อมูลโดยใช้ข้อความภาษาอังกฤษ หากคุณแทรกพารามิเตอร์ ที่อยู่ "15 Bay Street, Laurel, CA" ลงในข้อความ RTL โดยไม่ให้ การแนะนำเกี่ยวกับทิศทางข้อความ ผลลัพธ์ไม่เป็นไปตามที่คาดหวังหรือไม่ถูกต้อง:

六➔ בבריค์ต้องการลบ ל 15 Bay Street, Laurel, CA?

บ้านเลขที่ปรากฏทางด้านขวาของที่อยู่ ไม่ใช่ ออกตามที่ควรจะเป็น ทำให้บ้านเลขที่ดูเหมือนกับไปรษณีย์แปลกๆ มากขึ้น โค้ด ปัญหาเดียวกันนี้อาจเกิดขึ้นถ้าคุณใส่ข้อความขวา (RTL) ไว้ในข้อความที่ ใช้ทิศทางข้อความ LTR

คำอธิบายและวิธีแก้ปัญหา

ปัญหาในตัวอย่างนี้เกิดขึ้นเนื่องจากตัวจัดรูปแบบข้อความไม่ ระบุว่า "15" เป็นส่วนหนึ่งของที่อยู่ ดังนั้น ระบบจึงไม่สามารถระบุได้ว่า "15" เป็นส่วนหนึ่งของข้อความ RTL ที่อยู่ก่อนข้อความ หรือข้อความ LTR ที่เข้ามา หลังจากนั้น

หากต้องการแก้ไขปัญหานี้ ให้ใช้เมธอด unicodeWrap() จาก BidiFormatter วิธีนี้จะตรวจหาทิศทางของสตริงและห่อหุ้มไว้ใน Unicode อักขระการจัดรูปแบบที่ประกาศทิศทางนั้น

ข้อมูลโค้ดต่อไปนี้สาธิตวิธีใช้ unicodeWrap():

Kotlin

val mySuggestion = "15 Bay Street, Laurel, CA"
val myBidiFormatter: BidiFormatter = BidiFormatter.getInstance()

// The "did_you_mean" localized string resource includes
// a "%s" placeholder for the suggestion.
String.format(getString(R.string.did_you_mean), myBidiFormatter.unicodeWrap(mySuggestion))

Java

String mySuggestion = "15 Bay Street, Laurel, CA";
BidiFormatter myBidiFormatter = BidiFormatter.getInstance();

// The "did_you_mean" localized string resource includes
// a "%s" placeholder for the suggestion.
String.format(getString(R.string.did_you_mean),
        myBidiFormatter.unicodeWrap(mySuggestion));

เนื่องจาก "15" จะปรากฏภายในข้อความที่ ประกาศว่าเป็น LTR และแสดงในตำแหน่งที่ถูกต้อง:

ホテ ปลาพลโฆษณาใหม่ וกรอบ ל 15 ถนน แขวง เมือง ลอเรล แคลิฟอร์เนีย ?

ใช้เมธอด unicodeWrap() ใน ข้อความทุกส่วนที่คุณแทรกลงในข้อความที่แปลแล้ว ยกเว้นในกรณีต่อไปนี้

  • กำลังแทรกข้อความลงในสตริงที่เครื่องอ่านได้ เช่น URI หรือคำสั่ง SQL
  • คุณทราบว่าข้อความส่วนนั้นมีการรวมอย่างเหมาะสมแล้ว

หมายเหตุ: หากแอปกำหนดเป้าหมายเป็น Android 4.3 (API ระดับ 18) หรือ ให้ใช้เวอร์ชัน BidiFormatter ที่พบใน Android Framework หรือไม่เช่นนั้น ให้ใช้เวอร์ชันของ BidiFormatter อยู่ในไลบรารีการสนับสนุน

จัดรูปแบบตัวเลข

ใช้ รูปแบบ สตริง (ไม่ใช่การเรียกเมธอด) เพื่อแปลงตัวเลขเป็นสตริงในแอป ตรรกะ:

Kotlin

var myIntAsString = "$myInt"

Java

String myIntAsString = String.format("%d", myInt);

วิธีนี้จะจัดรูปแบบตัวเลขให้เหมาะกับภาษาของคุณ ซึ่งอาจ รวมโดยใช้ชุดตัวเลขอื่น

เมื่อคุณใช้ String.format()เพื่อสร้าง การค้นหา SQL ในอุปกรณ์ที่ตั้งค่าเป็นภาษาที่ใช้ชุดตัวเลขของตนเอง เช่น ภาษาเปอร์เซีย และภาษาอาหรับส่วนใหญ่ จะเกิดปัญหาหากมีพารามิเตอร์ที่ไปยังข้อความค้นหา เป็นตัวเลข เนื่องจากหมายเลขอยู่ในรูปแบบตัวเลขของภาษา และ ตัวเลขเหล่านี้ไม่ถูกต้องใน SQL

หากต้องการเก็บตัวเลขในรูปแบบ ASCII ไว้ และดูแลให้คำค้นหา SQL ถูกต้อง คุณจะต้องใช้ เวอร์ชันที่ทำงานหนักเกินไปของ String.format()ที่ มีภาษาเป็นพารามิเตอร์แรก ใช้อาร์กิวเมนต์ภาษา Locale.US

รองรับการมิเรอร์เลย์เอาต์

ผู้ที่ใช้สคริปต์ RTL ชอบอินเทอร์เฟซผู้ใช้ RTL ซึ่งรวมถึง เมนูที่จัดชิดขวา ข้อความที่จัดชิดขวา และลูกศรไปข้างหน้าซึ่งชี้ไปที่ ออกไปแล้ว

รูปที่ 4 แสดงคอนทราสต์ระหว่างหน้าจอเวอร์ชัน LTR ภายใน แอปการตั้งค่าและคู่หู RTL:

วันที่ พื้นที่แจ้งเตือนจะอยู่ในแนวขวาใกล้มุมขวาบน
           ปุ่มเมนูในแถบแอปอยู่ใกล้กับมุมซ้ายบน
           เนื้อหาในส่วนหลักของหน้าจออยู่ในแนวซ้ายและปรากฏ
           LTR และปุ่มย้อนกลับอยู่ใกล้มุมซ้ายล่างและ
           ชี้ไปทางซ้าย พื้นที่การแจ้งเตือนจะอยู่ในแนวซ้ายใกล้กับมุมบนซ้าย
            ในแถบแอปใกล้มุมขวาบน เนื้อหา
            ในส่วนหลักของหน้าจอจะอยู่ในแนวขวาและปรากฏเป็นขวาไปซ้าย และ
            ปุ่มย้อนกลับจะอยู่ใกล้กับมุมขวาล่างและชี้ไปยัง
            ด้านขวา
รูปที่ 4 ตัวแปร LTR และ RTL ของหน้าจอการตั้งค่า

เมื่อเพิ่มการสนับสนุน RTL ลงในแอป ให้ ประเด็นต่อไปนี้

  • รองรับการมิเรอร์ข้อความ RTL เฉพาะในแอปเมื่อใช้ในอุปกรณ์ที่ใช้งาน Android 4.2 (API ระดับ 17) ขึ้นไป ดูวิธีรองรับการมิเรอร์ข้อความ ในอุปกรณ์รุ่นเก่า โปรดดูที่ให้การสนับสนุน สำหรับแอปเดิมในคู่มือนี้
  • ในการทดสอบว่าแอปรองรับทิศทางข้อความขวา (RTL) หรือไม่ ทดสอบโดยใช้ตัวเลือกสำหรับนักพัฒนาแอปตามที่อธิบายไว้ในคู่มือนี้และเชิญผู้อื่น ที่ใช้สคริปต์ RTL เพื่อใช้แอปของคุณ

หมายเหตุ: หากต้องการดูหลักเกณฑ์การออกแบบเพิ่มเติมที่เกี่ยวข้องกับ การมิเรอร์เลย์เอาต์ รวมถึงรายการองค์ประกอบที่เหมาะสมและไม่เหมาะสม ในการมิเรอร์ ให้ดูที่ แบบ 2 ทิศทาง หลักเกณฑ์ดีไซน์ Material

หากต้องการมิเรอร์เลย์เอาต์ UI ในแอปให้ปรากฏเป็น RTL ในภาษา RTL โปรดทำตามขั้นตอนในส่วนต่อไปนี้

แก้ไขไฟล์บิลด์และไฟล์ Manifest

แก้ไขไฟล์ build.gradle ของโมดูลแอปและไฟล์ Manifest ของแอป ดังนี้

build.gradle (Module: app)

ดึงดูด

android {
    ...
    defaultConfig {
        targetSdkVersion 17 // Or higher
        ...
    }
}

Kotlin

android {
    ...
    defaultConfig {
        targetSdkVersion(17) // Or higher
        ...
    }
}

AndroidManifest.xml

<manifest ... >
    ...
    <application ...
        android:supportsRtl="true">
    </application>
</manifest>

หมายเหตุ: หากแอปกำหนดเป้าหมายเป็น Android 4.1.1 (API ระดับ 16) หรือ ระบบจะไม่สนใจแอตทริบิวต์ android:supportsRtl รวมถึงแอตทริบิวต์ ค่าแอตทริบิวต์ start และ end ที่ปรากฏใน ไฟล์เค้าโครงของแอป ในกรณีนี้ การมิเรอร์เลย์เอาต์ RTL จะไม่เกิดขึ้น ในแอปของคุณโดยอัตโนมัติ

อัปเดตทรัพยากรที่มีอยู่

แปลง left และ right เป็น start และ end ตามลำดับในไฟล์ทรัพยากรสำหรับเลย์เอาต์ที่มีอยู่ ซึ่งจะช่วยให้เฟรมเวิร์กปรับองค์ประกอบ UI ของแอปตาม การตั้งค่าภาษาของผู้ใช้

หมายเหตุ: ก่อนอัปเดตทรัพยากร โปรดดูวิธี ให้การสนับสนุนสำหรับแอปเดิม หรือ แอปที่กำหนดเป้าหมายเป็น Android 4.1.1 (API ระดับ 16) และต่ำกว่า

หากต้องการใช้ความสามารถในการจัดตำแหน่ง RTL ของเฟรมเวิร์ก ให้เปลี่ยนแอตทริบิวต์ใน ไฟล์เลย์เอาต์ที่ปรากฏในตาราง 1

ตาราง 1. แอตทริบิวต์สำหรับ ใช้เมื่อแอปของคุณรองรับข้อความทิศทางหลายทิศทาง

แอตทริบิวต์ที่รองรับ LTR เท่านั้น แอตทริบิวต์ที่รองรับ LTR และ RTL
android:gravity="left" android:gravity="start"
android:gravity="right" android:gravity="end"
android:layout_gravity="left" android:layout_gravity="start"
android:layout_gravity="right" android:layout_gravity="end"
android:paddingLeft android:paddingStart
android:paddingRight android:paddingEnd
android:drawableLeft android:drawableStart
android:drawableRight android:drawableEnd
android:layout_alignLeft android:layout_alignStart
android:layout_alignRight android:layout_alignEnd
android:layout_marginLeft android:layout_marginStart
android:layout_marginRight android:layout_marginEnd
android:layout_alignParentLeft android:layout_alignParentStart
android:layout_alignParentRight android:layout_alignParentEnd
android:layout_toLeftOf android:layout_toStartOf
android:layout_toRightOf android:layout_toEndOf

ตารางที่ 2 แสดงวิธีที่ระบบจัดการแอตทริบิวต์การจัดแนว UI โดยอิงจาก เวอร์ชัน SDK เป้าหมาย ไม่ว่าจะเป็นแอตทริบิวต์ left และ right กำหนด และระบุว่าแอตทริบิวต์ start และ end มีการ กำหนดไว้

ตาราง 2. ตามลักษณะการปรับแนวองค์ประกอบ UI ในเวอร์ชัน SDK เป้าหมายและแอตทริบิวต์ที่กำหนดไว้

การกำหนดเป้าหมายเป็น Android 4.2
(API ระดับ 17) หรือ สูงกว่าปกติ
ซ้ายและขวาหมายถึงอะไร กำหนดจุดเริ่มต้นและสิ้นสุดไหม ผลลัพธ์
ใช่ ได้ ใช่ มีการใช้ start และ end กำลังลบล้าง left และ right
ใช่ ได้ ไม่ ใช้ left และ right แล้ว
ใช่ ไม่ได้ ใช่ ใช้ start และ end แล้ว
ไม่ ได้ ใช่ ใช้ left และ right (start และ ระบบจะไม่พิจารณา end)
ไม่ ใช่ ไม่ ใช้ left และ right แล้ว
ไม่ ไม่ได้ ใช่ start และ end เปลี่ยนเป็น left และ right

เพิ่มแหล่งข้อมูลเกี่ยวกับเส้นทางและภาษาที่เฉพาะเจาะจง

ขั้นตอนนี้จะต้องมีการเพิ่มเลย์เอาต์ เวอร์ชันที่ถอนออกได้ และเวอร์ชันที่เฉพาะเจาะจง กำหนดค่าไฟล์ทรัพยากรที่มีค่าที่ปรับแต่งสำหรับภาษาต่างๆ และข้อความแนะนำเส้นทาง

ใน Android 4.2 (API ระดับ 17) ขึ้นไป คุณสามารถใช้ -ldrtl (layout-direction-ขวาไปซ้าย) และ -ldltr (layout-direction-ซ้ายไปขวา) ตัวระบุทรัพยากร เพื่อย้อนกลับ ความเข้ากันได้กับทรัพยากรที่มีอยู่แล้ว Android เวอร์ชันเก่าจะใช้ ตัวระบุภาษาของทรัพยากร เพื่อให้อนุมานทิศทางของข้อความที่ถูกต้องได้

สมมติว่าคุณต้องการเพิ่มไฟล์เลย์เอาต์ที่เฉพาะเจาะจงเพื่อรองรับสคริปต์ RTL เช่น ภาษาฮีบรู อาหรับ และเปอร์เซีย ในการดำเนินการนี้ ให้เพิ่ม ไดเรกทอรี layout-ldrtl/ ในไดเรกทอรี res/ ของคุณในรูปแบบ ที่แสดงในตัวอย่างต่อไปนี้

res/
    layout/
        main.xml This layout file is loaded by default.
    layout-ldrtl/
        main.xml This layout file is loaded for languages using an
                 RTL text direction, including Arabic, Persian, and Hebrew.

ถ้าคุณต้องการเพิ่มการออกแบบเฉพาะที่ออกแบบมาสำหรับ ข้อความภาษาอาหรับ โครงสร้างไดเรกทอรีจะมีลักษณะดังนี้

res/
    layout/
        main.xml This layout file is loaded by default.
    layout-ar/
        main.xml This layout file is loaded for Arabic text.
    layout-ldrtl/
        main.xml This layout file is loaded only for non-Arabic
                 languages that use an RTL text direction.

หมายเหตุ: ทรัพยากรเฉพาะภาษาจะมีความสำคัญสูงกว่า ทรัพยากรเฉพาะทิศทางการจัดวาง ซึ่งมีลำดับความสำคัญเหนือค่าเริ่มต้น ที่ไม่ซับซ้อน

ใช้วิดเจ็ตที่รองรับ

สำหรับ Android 4.2 (API ระดับ 17) องค์ประกอบ UI ของเฟรมเวิร์กส่วนใหญ่รองรับ RTL ทิศทางข้อความโดยอัตโนมัติ อย่างไรก็ตาม องค์ประกอบต่างๆ ของเฟรมเวิร์ก เช่น ViewPager ไม่รองรับข้อความ RTL เส้นทางการเรียนรู้

วิดเจ็ตบนหน้าจอหลักรองรับทิศทางข้อความขวาไปซ้ายตราบเท่าที่ ไฟล์ Manifest ที่เกี่ยวข้องจะมีการกำหนดแอตทริบิวต์ android:supportsRtl="true"

ให้การสนับสนุนสำหรับแอปเดิม

หากแอปกำหนดเป้าหมายเป็น Android 4.1.1 (API ระดับ 16) หรือต่ำกว่า ให้ใส่ แอตทริบิวต์ left และ right นอกเหนือจาก start และ end

หากต้องการตรวจสอบว่าเลย์เอาต์ต้องใช้ทิศทางข้อความขวาไปซ้ายหรือไม่ ให้ใช้ ตรรกะต่อไปนี้

Kotlin

private fun shouldUseLayoutRtl(): Boolean {
    return if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
        View.LAYOUT_DIRECTION_RTL == layoutDirection
    } else {
        false
    }
}

Java

private boolean shouldUseLayoutRtl() {
    if (android.os.Build.VERSION.SDK_INT >=
            android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
        return View.LAYOUT_DIRECTION_RTL == getLayoutDirection();
    } else {
        return false;
    }
}

หมายเหตุ: ใช้เวอร์ชัน 23.0.1 เพื่อหลีกเลี่ยงปัญหาความเข้ากันได้ หรือสูงกว่า แอนดรอยด์ เครื่องมือสร้าง SDK

ทดสอบโดยใช้ตัวเลือกสำหรับนักพัฒนาแอป

ในอุปกรณ์ที่ใช้ Android 4.4 (API ระดับ 19) ขึ้นไป คุณสามารถเปิดใช้ บังคับทิศทางการจัดวาง RTL ใน ตัวเลือกสำหรับนักพัฒนาแอปในอุปกรณ์ การตั้งค่านี้ ช่วยให้คุณเห็นข้อความที่ใช้สคริปต์ LTR เช่น ข้อความภาษาอังกฤษ ใน RTL

อัปเดตตรรกะแอป

ส่วนนี้จะอธิบายแง่มุมเฉพาะเกี่ยวกับตรรกะของแอปสำหรับ อัปเดตเมื่อปรับแอปให้รองรับการรับส่งข้อความหลายทิศทาง

การเปลี่ยนแปลงพร็อพเพอร์ตี้

วิธีจัดการการเปลี่ยนแปลงพร็อพเพอร์ตี้ที่เกี่ยวข้องกับ RTL เช่น เลย์เอาต์ ทิศทาง พารามิเตอร์เลย์เอาต์ ระยะห่างจากขอบ ทิศทางข้อความ การจัดข้อความ หรือ การจัดตำแหน่งที่ถอนออกได้ onRtlPropertiesChanged() Callback Callback นี้จะช่วยให้คุณสามารถดูทิศทางของเลย์เอาต์ปัจจุบันและ อัปเดตออบเจ็กต์ View ของกิจกรรมให้สอดคล้องกัน

ยอดดู

หากคุณกำลังสร้างวิดเจ็ต UI ที่ไม่ได้เป็นส่วนหนึ่งของกิจกรรมโดยตรง ดูลำดับชั้น เช่น กล่องโต้ตอบหรือองค์ประกอบ UI ที่คล้ายข้อความโทสต์ ให้ตั้งค่า ทิศทางการจัดวางตามบริบท ข้อมูลโค้ดต่อไปนี้ สาธิตวิธีทำขั้นตอนนี้ให้เสร็จสมบูรณ์:

Kotlin

val config: Configuration = context.resources.configuration
view.layoutDirection = config.layoutDirection

Java

final Configuration config =
    getContext().getResources().getConfiguration();
view.setLayoutDirection(config.getLayoutDirection());

มีหลายเมธอดสำหรับคลาส View ที่ต้องมีฟังก์ชันเพิ่มเติม การพิจารณา:

onMeasure()
การวัดยอดดูอาจแตกต่างกันไปตามทิศทางข้อความ
onLayout()
หากสร้างการติดตั้งใช้งานเลย์เอาต์ของตัวเอง คุณจะต้องเรียกใช้ super() ใน onLayout() เวอร์ชันของคุณและปรับ ตรรกะที่กำหนดเองของคุณเพื่อรองรับสคริปต์ RTL
onDraw()
หากคุณกำลังใช้มุมมองที่กำหนดเองหรือเพิ่มฟังก์ชันการทำงานขั้นสูงลงใน คุณต้องอัปเดตโค้ดของคุณ เพื่อให้สนับสนุนสคริปต์ RTL ใช้เมนู โค้ดต่อไปนี้เพื่อระบุว่าวิดเจ็ตอยู่ในโหมด RTL หรือไม่

Kotlin

// On devices running Android 4.1.1 (API level 16) and lower,
// you can call the isLayoutRtl() system method directly.
fun isLayoutRtl(): Boolean = layoutDirection == LAYOUT_DIRECTION_RTL

Java

// On devices running Android 4.1.1 (API level 16) and lower,
// you can call the isLayoutRtl() system method directly.
public boolean isLayoutRtl() {
    return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
}

เนื้อหาที่ถอนออกได้

หากคุณมีอุปกรณ์ที่ถอนออกได้ที่ต้องมิเรอร์สำหรับเลย์เอาต์ RTL โปรดดำเนินการให้เสร็จสมบูรณ์ ขั้นตอนใดขั้นตอนหนึ่งต่อไปนี้ขึ้นอยู่กับเวอร์ชันของ Android ที่ทำงานอยู่ในอุปกรณ์

  • สำหรับอุปกรณ์ที่ใช้ Android 4.3 (API ระดับ 18) และต่ำกว่า เพิ่มและกำหนดไฟล์ทรัพยากร -ldrtl
  • ใน Android 4.4 (API ระดับ 19) ขึ้นไป ให้ใช้ android:autoMirrored="true" เมื่อกำหนดโฆษณาที่ถอนออกได้ ซึ่งช่วยให้ระบบจัดการ การมิเรอร์เค้าโครง RTL ให้คุณได้

    หมายเหตุ: android:autoMirrored ใช้ได้กับไฟล์แบบถอนออกได้อย่างง่ายที่มีการมิเรอร์ 2 ทิศทาง เป็นเพียงภาพกราฟิกของภาพที่ถอนออกได้ทั้งหมด หากถอนออกได้ มีองค์ประกอบหลายอย่างหรือหากแสดงให้เห็นถึงการเปลี่ยนแปลงที่ถอนออกได้ของคุณ คุณสามารถทำการมิเรอร์ด้วยตนเองได้ เมื่อใดก็ตามที่ ให้ตรวจสอบกับผู้เชี่ยวชาญแบบ 2 ทิศทางเพื่อดูว่า เนื้อหาที่ถอนออกได้แบบมิเรอร์จะเป็นประโยชน์ต่อผู้ใช้

แรงโน้มถ่วง

หากโค้ดเลย์เอาต์ของแอปใช้ Gravity.LEFT หรือ Gravity.RIGHT เปลี่ยนรายการเหล่านี้ ค่าไปยัง Gravity.START และ Gravity.END ตามลำดับ

หากคุณมีโค้ด Kotlin หรือ Java ที่ขึ้นอยู่กับ พร็อพเพอร์ตี้ Gravity.LEFT หรือ Gravity.RIGHT คุณสามารถปรับใช้การเปลี่ยนแปลงนี้ได้โดยตั้งค่า absoluteGravity ให้ตรงกับ layoutDirection

ตัวอย่างเช่น หากคุณกำลังใช้โค้ดต่อไปนี้

Kotlin

when (gravity and Gravity.HORIZONTAL_GRAVITY_MASK) {
    Gravity.LEFT -> {
        // Handle objects that are left-aligned.
    }
    Gravity.RIGHT -> {
        // Handle objects that are right-aligned.
    }
}

Java

switch (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
    case Gravity.LEFT:
        // Handle objects that are left-aligned.
        break;
    case Gravity.RIGHT:
        // Handle objects that are right-aligned.
        break;
}

เปลี่ยนเป็นค่าต่อไปนี้

Kotlin

val absoluteGravity: Int = Gravity.getAbsoluteGravity(gravity, layoutDirection)
when (absoluteGravity and Gravity.HORIZONTAL_GRAVITY_MASK) {
    Gravity.LEFT -> {
        // Handle objects that are left-aligned.
    }
    Gravity.RIGHT -> {
        // Handle objects that are right-aligned.
    }
}

Java

final int layoutDirection = getLayoutDirection();
final int absoluteGravity =
        Gravity.getAbsoluteGravity(gravity, layoutDirection);
switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
    case Gravity.LEFT:
        // Handle objects that are left-aligned.
        break;
    case Gravity.RIGHT:
        // Handle objects that are right-aligned.
        break;
}

ซึ่งหมายความว่าคุณสามารถเก็บโค้ดที่มีอยู่ ซึ่งจัดการผลลัพธ์ตามด้านซ้ายและ ค่าที่ตรงกัน แม้ว่าคุณจะใช้ start และ end สำหรับค่าแรงโน้มถ่วง

หมายเหตุ: เมื่อใช้การตั้งค่าแรงโน้มถ่วง ให้ใช้ Gravity.apply() เวอร์ชันโอเวอร์โหลดที่มี อาร์กิวเมนต์ layoutDirection

ขอบและระยะห่างจากขอบ

หากต้องการรองรับสคริปต์ RTL ในแอป ให้ทําตามแนวทางปฏิบัติแนะนําเหล่านี้ที่เกี่ยวข้องกับ ค่าระยะขอบและระยะห่างจากขอบ

  • ใช้ getMarginStart() และ getMarginEnd() แทนที่จะเป็น แอตทริบิวต์เฉพาะเส้นทางเทียบเท่ากับ leftMargin และ rightMargin
  • เมื่อใช้ setMargins() ให้สลับค่าของ left และ right อาร์กิวเมนต์หากแอปตรวจพบสคริปต์ RTL
  • หากแอปของคุณมีตรรกะระยะห่างจากขอบที่กำหนดเอง ให้ลบล้าง setPadding() และ setPaddingRelative()

รองรับค่ากำหนดภาษาที่ใช้ในแอป

ในหลายกรณี ผู้ใช้หลายภาษาตั้งค่าภาษาของระบบของตนเป็นภาษาเดียว เช่น ภาษาอังกฤษ แต่ พวกเขาต้องการเลือกภาษาอื่น สำหรับบางแอป เช่น ดัตช์ จีน หรือฮินดี ให้ความช่วยเหลือ มอบประสบการณ์ที่ดีขึ้นให้แก่ผู้ใช้เหล่านี้ Android 13 ได้เปิดตัวฟีเจอร์ต่อไปนี้สำหรับ แอปที่รองรับหลายภาษา

  • การตั้งค่าระบบ: พื้นที่ส่วนกลางที่ผู้ใช้สามารถเลือก ภาษาที่ต้องการสำหรับแต่ละแอป

    แอปของคุณต้องประกาศแอตทริบิวต์ android:localeConfig ใน ไฟล์ Manifest เพื่อบอกระบบว่ารองรับหลายภาษา ดูข้อมูลเพิ่มเติมได้ที่ วิธีการสำหรับ การสร้างทรัพยากร และประกาศในไฟล์ Manifest ของแอป

  • API เพิ่มเติม: API สาธารณะเหล่านี้ เช่น setApplicationLocales() และ getApplicationLocales() ใน LocaleManager อนุญาตให้แอปตั้งค่าภาษาอื่นจากภาษาของระบบที่ รันไทม์

    แอปที่ใช้เครื่องมือเลือกภาษาในแอปแบบกำหนดเองสามารถใช้ API เหล่านี้เพื่อให้ผู้ใช้ มอบประสบการณ์ของผู้ใช้ที่สอดคล้องกัน ไม่ว่าผู้ใช้จะเลือกภาษาใดก็ตาม การตั้งค่าเริ่มต้น นอกจากนี้ API สาธารณะยังช่วยลดจำนวนของโค้ดสำเร็จรูป และ แอปเหล่านั้นรองรับ APK แยก และยังสนับสนุนการสำรองข้อมูลอัตโนมัติ สำหรับแอปเพื่อจัดเก็บการตั้งค่าภาษาของผู้ใช้ระดับแอป

    สำหรับความเข้ากันได้แบบย้อนหลังกับ Android เวอร์ชันก่อนหน้า จะมี API ที่เทียบเท่าให้ใช้งานเช่นกัน ใน AndroidX เราขอแนะนำให้ใช้ Appcompat 1.6.0-beta01 หรือ สูงขึ้น

    หากต้องการเรียนรู้เพิ่มเติม โปรดดูวิธีการสำหรับ การนำเทคโนโลยี API

ดูเพิ่มเติม

แหล่งข้อมูลเพิ่มเติม

หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับการรองรับอุปกรณ์รุ่นเก่า โปรดดูแหล่งข้อมูลต่อไปนี้

บล็อกโพสต์