edge
เพิ่มเติมที่ rubyonrails.org: เพิ่มเติมเกี่ยวกับ Ruby on Rails

API การระบุภาษาสากล (I18n) ของ Rails

แพ็กเกจ Ruby I18n (ย่อมาจาก internationalization) ซึ่งถูกส่งพร้อมกับ Ruby on Rails (เริ่มต้นตั้งแต่ Rails 2.2) ให้เครื่องมือที่ใช้งานง่ายและสามารถขยายตัวได้สำหรับการ แปลแอปพลิเคชันของคุณเป็นภาษาที่กำหนดเอง นอกเหนือจากภาษาอังกฤษหรือสำหรับการ สนับสนุนหลายภาษา ในแอปพลิเคชันของคุณ

กระบวนการ "internationalization" ทั่วไปแล้วหมายถึงการแยกสตริงและส่วนอื่น ๆ ที่เฉพาะเจาะจงตามภาษา (เช่นรูปแบบวันที่หรือสกุลเงิน) ออกจากแอปพลิเคชันของคุณ กระบวนการ "localization" หมายถึงการให้คำแปลและรูปแบบที่เป็นภาษาท้องถิ่นสำหรับส่วนเหล่านี้1

ดังนั้นในกระบวนการ internationalizing แอปพลิเคชัน Rails ของคุณคุณต้อง:

ในกระบวนการ localizing แอปพลิเคชันของคุณคุณอาจต้องทำสิ่งต่อไปนี้:

คู่มือนี้จะแนะนำวิธีใช้ I18n API และประกอบด้วยบทแนะนำเกี่ยวกับวิธีการทำให้แอปพลิเคชัน Rails รองรับการใช้งานระหว่างประเทศตั้งแต่เริ่มต้น

หลังจากอ่านคู่มือนี้คุณจะรู้:

Chapters

  1. วิธีการทำงานของ I18n ใน Ruby on Rails
  2. การนำเสนอและการใช้งานในระดับสากล
  3. ภาพรวมของคุณลักษณะ API ของ I18n
  4. วิธีการเก็บการแปลที่กำหนดเอง
  5. ปรับแต่งการตั้งค่า I18n ของคุณ
  6. สรุป
  7. การมีส่วนร่วมใน Rails I18n
  8. ทรัพยากร
  9. ผู้เขียน
  10. เชิงอรรถ

หมายเหตุ: กรอบการใช้งาน Ruby I18n จะให้คุณมีเครื่องมือที่จำเป็นสำหรับการระบุภาษาสากล / การแปลภาษาของแอปพลิเคชัน Rails ของคุณ คุณยังสามารถใช้แพ็กเกจต่าง ๆ ที่มีอยู่เพิ่มเติมเพื่อเพิ่มฟังก์ชันหรือคุณสมบัติเพิ่มเติม ดู แพ็กเกจ rails-i18n เพื่อข้อมูลเพิ่มเติม

1 วิธีการทำงานของ I18n ใน Ruby on Rails

การระบุภาษาสากลเป็นปัญหาที่ซับซ้อน ภาษาธรรมชาติแตกต่างกันในหลายๆ ด้าน (เช่นกฎการเปลี่ยนรูปพจนานุกรม) ซึ่งทำให้ยากที่จะให้เครื่องมือสำหรับแก้ปัญหาทั้งหมดได้พร้อมกัน ด้วยเหตุนี้ API I18n ของ Rails มุ่งเน้นที่:

  • การให้การสนับสนุนสำหรับภาษาอังกฤษและภาษาที่คล้ายกันอื่นๆ ในตัว
  • การทำให้ง่ายต่อการปรับแต่งและขยายความสามารถทั้งหมดสำหรับภาษาอื่นๆ

เป็นส่วนหนึ่งของการแก้ปัญหานี้ สตริงแบบสถิต ในกรอบการทำงานของ Rails - เช่นข้อความการตรวจสอบ Active Record, รูปแบบเวลาและวันที่ - ได้รับการระบุภาษาสากล การ localization ของแอปพลิเคชัน Rails หมายถึงการกำหนดค่าที่แปลสำหรับสตริงเหล่านี้ในภาษาที่ต้องการ

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

1.1 โครงสร้างโดยรวมของไลบรารี

ดังนั้น แพ็กเกจ Ruby I18n ถูกแบ่งออกเป็นสองส่วน:

  • ส่วน API สาธารณะของกรอบการทำงาน I18n - โมดูล Ruby ที่มีเมธอดสาธารณะที่กำหนดวิธีการทำงานของไลบรารี
  • ส่วน backend เริ่มต้น (ที่มีชื่อ Simple backend) ซึ่งดำเนินการดังนี้

เป็นผู้ใช้คุณควรเข้าถึงเฉพาะเมธอดสาธารณะบนโมดูล I18n เท่านั้น แต่มันก็เป็นประโยชน์ที่จะทราบถึงความสามารถของ backend หมายเหตุ: สามารถแทนที่ Simple backend ที่จัดส่งมาด้วย backend ที่มีกำลังมากกว่าซึ่งจะเก็บข้อมูลการแปลในฐานข้อมูลที่เกี่ยวข้อง, พจนานุกรม GetText หรือคล้ายกัน ดูในส่วน การใช้ backend ที่แตกต่างกัน ด้านล่าง

1.2 สาธิต API สาธิต

เมธอดที่สำคัญที่สุดของ I18n API คือ:

translate # ค้นหาการแปลข้อความ
localize  # แปลงวัตถุวันที่และเวลาเป็นรูปแบบท้องถิ่น

เมธอดเหล่านี้มีชื่อย่อว่า #t และ #l ดังนั้นคุณสามารถใช้งานได้ดังนี้:

I18n.t 'store.title'
I18n.l Time.now

ยังมี attribute readers และ writers สำหรับแอตทริบิวต์ต่อไปนี้:

load_path                 # ประกาศไฟล์แปลกำหนดเอง
locale                    # รับและตั้งค่า locale ปัจจุบัน
default_locale            # รับและตั้งค่า locale เริ่มต้น
available_locales         # รับ locale ที่อนุญาตให้ใช้งานได้สำหรับแอปพลิเคชัน
enforce_available_locales # บังคับการอนุญาต locale (true หรือ false)
exception_handler         # ใช้ exception_handler ที่แตกต่างกัน
backend                   # ใช้ backend ที่แตกต่างกัน

ดังนั้นเรามานำเสนอวิธีการนำระบบรายการระหว่างประเทศเข้ากับแอปพลิเคชัน Rails ที่ง่ายที่สุดในบทถัดไป!

ตั้งค่าแอปพลิเคชัน Rails สำหรับการนำระบบรายการระหว่างประเทศเข้าใช้งาน


มีขั้นตอนเพียงไม่กี่ขั้นตอนเพื่อเริ่มต้นใช้งานระบบรายการระหว่างประเทศสำหรับแอปพลิเคชัน Rails

1.3 กำหนดค่าโมดูล I18n

ตามหลักการ convention over configuration ระบบรายการระหว่างประเทศของ Rails จะให้สตริงแปลเริ่มต้นที่เหมาะสม หากต้องการสตริงแปลที่แตกต่างกันสามารถแทนที่ได้

Rails จะเพิ่มไฟล์ .rb และ .yml ทั้งหมดจากไดเรกทอรี config/locales เข้าสู่ ที่อยู่โหลดรายการแปล โดยอัตโนมัติ

โลเคลที่เริ่มต้น en.yml ในไดเรกทอรีนี้มีคู่ตัวอย่างของสตริงแปล:

en:
  hello: "Hello world"

นั่นหมายความว่าในโลเคล :en คีย์ hello จะแมปไปยังสตริง Hello world สตริงทุกตัวภายใน Rails ถูกนำเข้าระบบรายการระหว่างประเทศในลักษณะนี้ ดูตัวอย่างข้อความการตรวจสอบ Active Model ในไฟล์ activemodel/lib/active_model/locale/en.yml หรือรูปแบบเวลาและวันที่ในไฟล์ activesupport/lib/active_support/locale/en.yml คุณสามารถใช้ YAML หรือ Hash ของ Ruby มาเก็บรายการแปลใน backend เริ่มต้น (Simple)

ไลบรารี I18n จะใช้ ภาษาอังกฤษ เป็น locale เริ่มต้น กล่าวคือหากไม่ได้ตั้งค่า locale ที่แตกต่างกัน :en จะถูกใช้สำหรับการค้นหาการแปล

หมายเหตุ: ไลบรารี i18n ใช้วิธีการที่เหมาะสมสำหรับกุญแจ locale (หลังจาก การสนทนาบางส่วน) ซึ่งรวมเฉพาะส่วน locale ("ภาษา") เช่น :en, :pl ไม่มีส่วน region เช่น :"en-US" หรือ :"en-GB" ซึ่งใช้เป็นแบ่ง "ภาษา" และ "การตั้งค่าภูมิภาค" หรือ "สำเนาภาษา" แบบดั้งเดิม แอปพลิเคชันระหว่างประเทศหลายแอปพลิเคชันใช้เฉพาะองค์ประกอบ "ภาษา" ของ locale เช่น :cs, :th, หรือ :es (สำหรับภาษาเช็ก, ไทย และสเปน) อย่างไรก็ตาม มีความแตกต่างทางภูมิภาคภายในกลุ่มภาษาต่าง ๆ ที่อาจเป็นสิ่งสำคัญ เช่น ในโลเคล :"en-US" คุณจะมีสัญลักษณ์สกุลเงินเป็น $ ในขณะที่ใน :"en-GB" คุณจะมี £ ไม่มีอะไรหยุดคุณจากการแยกการตั้งค่าภูมิภาคและอื่น ๆ ในทางนี้: คุณเพียงแต่ต้องให้ locale "ภาษาอังกฤษ - สหราชอาณาจักร" เต็มรูปแบบในพจนานุกรม :"en-GB" คุณสามารถเปลี่ยนภาษาเริ่มต้นและกำหนดพาธการโหลดแปลได้ใน config/application.rb ดังนี้:

config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}')]
config.i18n.default_locale = :de

จะต้องระบุพาธการโหลดก่อนที่จะค้นหาแปลภาษาใด ๆ เพื่อเปลี่ยนภาษาเริ่มต้นจากตัวกำหนดใน config/application.rb:

# config/initializers/locale.rb

# สถานที่ที่ไลบรารี I18n ควรค้นหาไฟล์แปล
I18n.load_path += Dir[Rails.root.join('lib', 'locale', '*.{rb,yml}')]

# ภาษาที่อนุญาตให้ใช้สำหรับแอปพลิเคชัน
I18n.available_locales = [:en, :pt]

# ตั้งค่าภาษาเริ่มต้นเป็นอย่างอื่นนอกเหนือจาก :en
I18n.default_locale = :pt

โปรดทราบว่าการเพิ่มโดยตรงไปยัง I18n.load_path แทนที่การกำหนดค่า I18n ที่กำหนดไว้ในแอปพลิเคชัน จะไม่ แทนที่แปลจากแพ็คเกจภายนอก

1.4 การจัดการภาษาในแต่ละคำขอ

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

ภาษาเริ่มต้นถูกใช้สำหรับแปลภาษาทั้งหมดยกเว้นใช้ I18n.locale= หรือ I18n.with_locale

I18n.locale อาจรั่วไหลเข้าสู่คำขอถัดไปที่ให้บริการโดยเธรด/กระบวนการเดียวกันหากไม่ได้ตั้งค่าไว้เสมอในทุก ๆ คอนโทรลเลอร์ ตัวอย่างเช่นการดำเนินการ I18n.locale =:es ในคำขอ POST หนึ่งจะมีผลต่อคำขอที่ต่อมาที่ไม่ได้ตั้งค่าภาษา แต่เฉพาะในกระบวนการเธรด/กระบวนการนั้นเท่านั้น ดังนั้น แทนที่ I18n.locale = คุณสามารถใช้ I18n.with_locale ซึ่งไม่มีปัญหาการรั่วไหลนี้

สามารถตั้งค่าภาษาได้ใน around_action ใน ApplicationController:

around_action :switch_locale

def switch_locale(&action)
  locale = params[:locale] || I18n.default_locale
  I18n.with_locale(locale, &action)
end

ตัวอย่างนี้แสดงให้เห็นการใช้พารามิเตอร์คิวรี URL เพื่อตั้งค่าภาษา (เช่น http://example.com/books?locale=pt) ด้วยวิธีนี้ http://localhost:3000?locale=pt จะแสดงผลเป็นภาษาโปรตุเกส ในขณะที่ http://localhost:3000?locale=de จะโหลดแปลงเยอรมัน

สามารถตั้งค่าภาษาได้โดยใช้วิธีหนึ่งในหลาย ๆ วิธีต่าง ๆ

1.4.1 ตั้งค่าภาษาจากชื่อโดเมน

หนึ่งในตัวเลือกที่คุณมีคือการตั้งค่าภาษาจากชื่อโดเมนที่แอปพลิเคชันของคุณทำงาน ตัวอย่างเช่น เราต้องการให้ www.example.com โหลดภาษาอังกฤษ (หรือภาษาเริ่มต้น) และ www.example.es โหลดภาษาสเปน ดังนั้น ชื่อโดเมนระดับสูง ถูกใช้สำหรับการตั้งค่าภาษา มีข้อดีหลายประการ:

  • ภาษาเป็นส่วนหนึ่งที่ ชัดเจน ของ URL
  • ผู้คนเข้าใจได้ง่ายว่าเนื้อหาจะแสดงเป็นภาษาใด
  • มันง่ายมากที่จะดำเนินการใน Rails
  • เครื่องมือค้นหาดูเหมือนชอบเนื้อหาในภาษาต่าง ๆ อยู่ในโดเมนที่แตกต่างกันและเชื่อมโยงกัน

คุณสามารถดำเนินการดังนี้ใน ApplicationController ของคุณ:

around_action :switch_locale

def switch_locale(&action)
  locale = extract_locale_from_tld || I18n.default_locale
  I18n.with_locale(locale, &action)
end

# รับภาษาจากชื่อโดเมนระดับสูงหรือส่งคืน +nil+ หากไม่มีภาษาดังกล่าว
# คุณต้องใส่บางอย่างเช่น:
#   127.0.0.1 application.com
#   127.0.0.1 application.it
#   127.0.0.1 application.pl
# ในไฟล์ /etc/hosts เพื่อลองใช้งานในเครื่องที่เป็นท้องถิ่น
def extract_locale_from_tld
  parsed_locale = request.host.split('.').last
  I18n.available_locales.map(&:to_s).include?(parsed_locale) ? parsed_locale : nil
end

เรายังสามารถตั้งค่าภาษาจาก subdomain ได้ในวิธีที่คล้ายกัน: ```ruby

รับรหัสภาษาจาก subdomain ของคำขอ (เช่น http://it.application.local:3000)

คุณต้องเพิ่มบางอย่างเช่น:

127.0.0.1 gr.application.local

ในไฟล์ /etc/hosts เพื่อทดสอบในเครื่อง localhost

def extract_locale_from_subdomain parsed_locale = request.subdomains.first I18n.available_locales.map(&:to_s).include?(parsed_locale) ? parsed_locale : nil end ```

หากแอปพลิเคชันของคุณมีเมนูสลับภาษา คุณจะต้องมีสิ่งที่คล้ายกันกับนี้:

link_to("Deutsch", "#{APP_CONFIG[:deutsch_website_url]}#{request.env['PATH_INFO']}")

โดยสมมติว่าคุณตั้งค่า APP_CONFIG[:deutsch_website_url] เป็นค่าใดค่าหนึ่ง เช่น http://www.application.de.

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

1.4.2 การตั้งค่าภาษาจากพารามิเตอร์ URL

วิธีที่ส่วนใหญ่ใช้ในการตั้งค่า (และส่งต่อ) ภาษาคือการรวมมันในพารามิเตอร์ URL เช่นเราทำใน I18n.with_locale(params[:locale], &action) around_action ในตัวอย่างแรก เราต้องการให้ URL ดูเช่น www.example.com/books?locale=ja หรือ www.example.com/ja/books ในกรณีนี้

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

การรับรหัสภาษาจาก params และตั้งค่าตามนั้นไม่ยาก แต่การรวมมันในทุก URL และดังนั้น ส่งผ่านคำขอ จะเป็นเรื่องยาก การรวมตัวเลือกชัดเจนในทุก URL เช่น link_to(books_url(locale: I18n.locale)) จะเป็นงานที่น่าเบื่อและอาจเป็นไปไม่ได้

Rails มีโครงสร้างพื้นฐานสำหรับ "การจัดการการตัดสินใจเกี่ยวกับ URL" ใน ApplicationController#default_url_options ซึ่งเป็นประโยชน์อย่างมากในสถานการณ์นี้: มันช่วยให้เราสามารถตั้งค่า "ค่าเริ่มต้น" สำหรับ url_for และเมธอดช่วยที่ขึ้นอยู่กับมัน (โดยการดำเนินการ/แทนที่ default_url_options)

เราสามารถรวมสิ่งที่คล้ายกันกับนี้ใน ApplicationController ได้ดังนี้:

# app/controllers/application_controller.rb
def default_url_options
  { locale: I18n.locale }
end

เมื่อใช้เมธอดช่วยที่ขึ้นอยู่กับ url_for (เช่นเมธอดช่วยสำหรับเส้นทางที่มีชื่อเช่น root_path หรือ root_url เส้นทางทรัพยากรเช่น books_path หรือ books_url เป็นต้น) จะ รวมรหัสภาษาในสตริงคิวรีสต์ ดังนี้: http://localhost:3001/?locale=ja

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

คุณอาจต้องการให้ URL ดูเช่นนี้: http://www.example.com/en/books (ภาษาอังกฤษ) และ http://www.example.com/nl/books (ภาษาดัตช์) สามารถทำได้ด้วยวิธี "การแทนที่ default_url_options" จากข้างต้น: คุณเพียงแค่ตั้งค่าเส้นทางของคุณด้วย scope:

# config/routes.rb
scope "/:locale" do
  resources :books
end

ตอนนี้เมื่อคุณเรียกใช้เมธอด books_path คุณควรได้ "/en/books" (สำหรับภาษาเริ่มต้น) URL เช่น http://localhost:3001/nl/books ควรโหลดภาษาดัตช์ และเมื่อเรียกใช้ books_path ต่อมาคุณควรได้ "/nl/books" (เนื่องจากมีการเปลี่ยนแปลงภาษา)

คำเตือน. เนื่องจากค่าที่ส่งกลับจาก default_url_options ถูกแคชต่อคำขอ ลิงก์ในตัวเลือกภาษาไม่สามารถสร้างขึ้นได้โดยเรียกใช้เมธอดช่วยในลูปที่ตั้งค่า I18n.locale ในแต่ละรอบ แทนที่นั่ง I18n.locale ไว้เดิมและส่งตัวเลือก :locale แบบชัดเจนให้กับเมธอดช่วย หรือแก้ไข request.original_fullpath หากคุณไม่ต้องการบังคับให้ใช้ locale ในเส้นทางของคุณ คุณสามารถใช้ scope เส้นทางทางเลือก (ที่ระบุโดยวงเล็บ) ได้ดังนี้:

# config/routes.rb
scope "(:locale)", locale: /en|nl/ do
  resources :books
end

ด้วยวิธีนี้ คุณจะไม่ได้รับข้อผิดพลาดในการเข้าถึงทรัพยากรของคุณ เช่น http://localhost:3001/books โดยไม่มี locale นี่เป็นประโยชน์เมื่อคุณต้องการใช้ locale เริ่มต้นเมื่อไม่ได้ระบุ

แน่นอนว่า คุณต้องดูแลเฉพาะ URL ราก (ที่เรียกว่า "homepage" หรือ "dashboard") ของแอปพลิเคชันของคุณ URL เช่น http://localhost:3001/nl จะไม่ทำงานโดยอัตโนมัติ เนื่องจากการประกาศ root to: "dashboard#index" ใน routes.rb ของคุณไม่พิจารณา locale (และถูกต้อง: มีเพียง URL เดียว)

คุณอาจต้องแมป URL เช่นเหล่านี้:

# config/routes.rb
get '/:locale' => 'dashboard#index'

คุณต้องดูแลเฉพาะเรื่องของเส้นทางของคุณ ลำดับ, เพื่อให้การประกาศเส้นทางนี้ไม่ "กิน" เส้นทางอื่น ๆ (คุณอาจต้องเพิ่มโดยตรงก่อนการประกาศ root :to)

หมายเหตุ: คุณควรดูที่ gem ต่าง ๆ ที่ทำให้ง่ายต่อการทำงานกับเส้นทาง: routing_filter, route_translator.

1.4.3 ตั้งค่า Locale จากการตั้งค่าของผู้ใช้

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

around_action :switch_locale

def switch_locale(&action)
  locale = current_user.try(:locale) || I18n.default_locale
  I18n.with_locale(locale, &action)
end

1.4.4 เลือก Locale ที่นำมาคาดเดา

เมื่อไม่ได้ตั้งค่า locale โดยชัดเจนสำหรับคำขอ (เช่นผ่านวิธีด้านบน) แอปพลิเคชันควรพยายามคาดเดา locale ที่ต้องการ

1.4.4.1 การคาดเดา Locale จากส่วนหัวภาษา

ส่วนหัว HTTP Accept-Language ระบุภาษาที่ต้องการสำหรับการตอบสนองของคำขอ บราวเซอร์ ตั้งค่าค่าส่วนหัวนี้ตามการตั้งค่าภาษาของผู้ใช้ ทำให้เป็นตัวเลือกแรกที่ดีเมื่อคาดเดา locale

การใช้ส่วนหัว Accept-Language อย่างง่ายจะเป็นดังนี้:

def switch_locale(&action)
  logger.debug "* Accept-Language: #{request.env['HTTP_ACCEPT_LANGUAGE']}"
  locale = extract_locale_from_accept_language_header
  logger.debug "* Locale set to '#{locale}'"
  I18n.with_locale(locale, &action)
end

private
  def extract_locale_from_accept_language_header
    request.env['HTTP_ACCEPT_LANGUAGE'].scan(/^[a-z]{2}/).first
  end

ในการปฏิบัติจริง จำเป็นต้องใช้โค้ดที่เสถียรมากขึ้นเพื่อทำให้สามารถทำได้เป็นประจำ ไลบรารี http_accept_language ของ Iain Hecker หรือ middleware Rack locale ของ Ryan Tomayko จะช่วยแก้ปัญหานี้

1.4.4.2 การคาดเดา Locale จาก IP Geolocation

ที่อยู่ IP ของไคลเอนต์ที่ทำคำขอสามารถใช้ในการคาดเดาภูมิภาคของไคลเอนต์และดังนั้น locale ของพวกเขา บริการเช่น GeoLite2 Country หรือ gem เช่น geocoder สามารถใช้ในการดำเนินการนี้ได้

โดยทั่วไป วิธีนี้น้อยเสียกว่าการใช้ส่วนหัวภาษาและไม่แนะนำสำหรับแอปพลิเคชันเว็บที่มากที่สุด

1.4.5 การเก็บ Locale จากเซสชันหรือคุกกี้

คำเตือน: คุณอาจจะมีความใจจะเก็บ locale ที่เลือกไว้ใน เซสชัน หรือ คุกกี้ อย่างไรก็ตาม อย่าทำเช่นนี้ locale ควรเป็นโปร่งใสและเป็นส่วนหนึ่งของ URL นี่จะทำให้คุณไม่ทำลายความคาดหวังพื้นฐานของผู้คนเกี่ยวกับเว็บเอง: หากคุณส่ง URL ไปยังเพื่อน พวกเขาควรเห็นหน้าเว็บและเนื้อหาเดียวกันกับคุณ คำที่เรียบง่ายสำหรับสิ่งนี้คือคุณกำลังเป็น RESTful อ่านเพิ่มเติมเกี่ยวกับการใช้วิธีการ RESTful ใน บทความของ Stefan Tilkov บางครั้งอาจมีข้อยกเว้นในกฎนี้และจะถูกพูดถึงด้านล่าง

2 การนำเสนอและการใช้งานในระดับสากล

ดี! ตอนนี้คุณได้เริ่มต้นการสนับสนุน I18n สำหรับแอปพลิเคชัน Ruby on Rails ของคุณและบอกให้มันใช้ locale ใด ๆ และวิธีการเก็บรักษามันระหว่างคำขอ

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

โดยใช้ตัวอย่างต่อไปนี้:

# config/routes.rb
Rails.application.routes.draw do
  root to: "home#index"
end
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  around_action :switch_locale

  def switch_locale(&action)
    locale = params[:locale] || I18n.default_locale
    I18n.with_locale(locale, &action)
  end
end
# app/controllers/home_controller.rb
class HomeController < ApplicationController
  def index
    flash[:notice] = "Hello Flash"
  end
end
<!-- app/views/home/index.html.erb -->
<h1>Hello World</h1>
<p><%= flash[:notice] %></p>

rails i18n demo untranslated

2.1 การแยกส่วนของรหัสที่ใช้งานได้ในระดับสากล

ในรหัสของเรา มีสตริงสองตัวที่เขียนเป็นภาษาอังกฤษที่จะถูกแสดงในการตอบสนองของเรา ("Hello Flash" และ "Hello World") เพื่อที่จะทำให้สามารถใช้งานได้ในระดับสากล สตริงเหล่านี้จำเป็นต้องถูกแทนที่ด้วยการเรียกใช้ #t ของ Rails พร้อมกับคีย์ที่เหมาะสมสำหรับแต่ละสตริง:

# app/controllers/home_controller.rb
class HomeController < ApplicationController
  def index
    flash[:notice] = t(:hello_flash)
  end
end
<!-- app/views/home/index.html.erb -->
<h1><%= t :hello_world %></h1>
<p><%= flash[:notice] %></p>

ตอนนี้ เมื่อมีการแสดงผลวิวนี้ มันจะแสดงข้อความข้อผิดพลาดที่บอกว่าข้อความแปลสำหรับคีย์ :hello_world และ :hello_flash หายไป

rails i18n demo translation missing

หมายเหตุ: Rails เพิ่มเมธอด t (translate) เข้าไปในวิวของคุณเพื่อให้คุณไม่ต้องพิมพ์ I18n.t ตลอดเวลา นอกจากนี้ เมธอดช่วยในการตรวจจับการแปลที่หายไปและห่อหุ้มข้อความข้อผิดพลาดที่ได้รับเป็น <span class="translation_missing">.

2.2 การให้บริการแปลสำหรับสตริงที่ใช้งานได้ในระดับสากล

เพิ่มการแปลที่หายไปลงในไฟล์พจนานุกรมแปล:

# config/locales/en.yml
en:
  hello_world: Hello world!
  hello_flash: Hello flash!
# config/locales/pirate.yml
pirate:
  hello_world: Ahoy World
  hello_flash: Ahoy Flash

เนื่องจาก default_locale ไม่เปลี่ยนแปลง การแปลใช้ locale :en และการตอบสนองจะแสดงสตริงภาษาอังกฤษ:

rails i18n demo translated to English

หาก locale ถูกตั้งค่าผ่าน URL เป็น locale ของโจรสลัด (http://localhost:3000?locale=pirate) การตอบสนองจะแสดงสตริงของโจรสลัด:

rails i18n demo translated to pirate

หมายเหตุ: คุณต้องรีสตาร์ทเซิร์ฟเวอร์เมื่อคุณเพิ่มไฟล์ locale ใหม่

คุณสามารถใช้ไฟล์ YAML (.yml) หรือไฟล์ Ruby (.rb) เพื่อเก็บแปลงานของคุณใน SimpleStore ได้ ไฟล์ YAML เป็นตัวเลือกที่นิยมในความคิดของนักพัฒนา Rails อย่างไรก็ตาม มันมีข้อเสียหนึ่ง คือ YAML มีความไวต่อช่องว่างและอักขระพิเศษ ดังนั้นแอปพลิเคชันอาจจะไม่โหลดพจนานุกรมของคุณได้อย่างถูกต้อง ไฟล์ Ruby จะทำให้แอปพลิเคชันของคุณล้มเหลวในคำขอแรก ดังนั้นคุณสามารถหาวิธีแก้ไขได้ง่าย (หากคุณพบปัญหา "ปัญหาแปลก ๆ" ในพจนานุกรม YAML ลองใส่ส่วนที่เกี่ยวข้องของพจนานุกรมของคุณลงในไฟล์ Ruby)

หากแปลงานของคุณถูกเก็บไว้ในไฟล์ YAML คุณต้องใช้การหนีตัวอักษรบางตัว ดังต่อไปนี้:

  • true, on, yes
  • false, off, no

ตัวอย่าง:

# config/locales/en.yml
en:
  success:
    'true':  'True!'
    'on':    'On!'
    'false': 'False!'
  failure:
    true:    'True!'
    off:     'Off!'
    false:   'False!'
I18n.t 'success.true'  # => 'True!'
I18n.t 'success.on'    # => 'On!'
I18n.t 'success.false' # => 'False!'
I18n.t 'failure.false' # => Translation Missing
I18n.t 'failure.off'   # => Translation Missing
I18n.t 'failure.true'  # => Translation Missing

2.3 การส่งตัวแปรไปยังการแปล

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

การสร้างคาดการณ์ที่ไม่ถูกต้องแสดงในตัวอย่างต่อไปนี้ ที่ทำการสร้างคาดการณ์เกี่ยวกับลำดับของส่วนต่าง ๆ ของการแปล โปรดทราบว่า Rails มีฟังก์ชันช่วยเหลือ number_to_currency เพื่อจัดการกรณีดังกล่าว

<!-- app/views/products/show.html.erb -->
<%= "#{t('currency')}#{@product.price}" %>
# config/locales/en.yml
en:
  currency: "$"
# config/locales/es.yml
es:
  currency: "€"

หากราคาสินค้าเป็น 10 แล้วการแปลที่ถูกต้องสำหรับภาษาสเปนคือ "10 €" แทนที่จะเป็น "€10" แต่การสร้างคาดการณ์ไม่สามารถให้ได้

เพื่อสร้างคาดการณ์ที่ถูกต้อง แพ็กเกจ I18n มาพร้อมกับคุณสมบัติที่เรียกว่าตัวแปร interpolation ซึ่งช่วยให้คุณสามารถใช้ตัวแปรในการกำหนดค่าแปลและส่งค่าสำหรับตัวแปรเหล่านี้ไปยังเมธอดแปล

ตัวอย่างการสร้างคาดการณ์ที่ถูกต้องแสดงดังนี้:

<!-- app/views/products/show.html.erb -->
<%= t('product_price', price: @product.price) %>
# config/locales/en.yml
en:
  product_price: "$%{price}"
# config/locales/es.yml
es:
  product_price: "%{price} €"

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

หมายเหตุ: คำสงวน default และ scope ไม่สามารถใช้เป็นชื่อตัวแปรได้ หากใช้งานจะเกิดข้อยกเว้น I18n::ReservedInterpolationKey หากการแปลคาดหวังว่าจะมีตัวแปร interpolation แต่ไม่ได้รับการส่งไปยัง #translate จะเกิดข้อยกเว้น I18n::MissingInterpolationArgument

2.4 เพิ่มรูปแบบวันที่/เวลา

โอเค! ตอนนี้เรามาเพิ่มการแสดงเวลาในหน้ามุมมอง เพื่อให้เราสามารถสาธิตฟีเจอร์การแปล วันที่/เวลา ได้ด้วย ในการแปลรูปแบบเวลาคุณสามารถส่งวัตถุเวลาไปยัง I18n.l หรือ (แนะนำ) ใช้ช่วยเหลือของ Rails #l คุณสามารถเลือกรูปแบบโดยส่งตัวเลือก :format - โดยค่าเริ่มต้นจะใช้รูปแบบ :default

<!-- app/views/home/index.html.erb -->
<h1><%= t :hello_world %></h1>
<p><%= flash[:notice] %></p>
<p><%= l Time.now, format: :short %></p>

และในไฟล์แปลภาษาโจรสำหรับเราเพิ่มรูปแบบเวลา (มันอยู่ในค่าเริ่มต้นของ Rails สำหรับภาษาอังกฤษแล้ว):

# config/locales/pirate.yml
pirate:
  time:
    formats:
      short: "arrrround %H'ish"

ดังนั้นนั่นคือ:

rails i18n demo localized time to pirate

เคล็ดลับ: ขณะนี้คุณอาจจะต้องเพิ่มรูปแบบวันที่/เวลาเพิ่มเติมเพื่อให้เครื่องมือ I18n ทำงานตามที่คาดหวัง (อย่างน้อยสำหรับภาษา 'pirate') แน่นอนว่ามีโอกาสที่ดีว่ามีคนทำงานทั้งหมดแล้วโดยการ แปลค่าเริ่มต้นของ Rails สำหรับภาษาของคุณ ดูที่ rails-i18n repository at GitHub เพื่อดูเอกสารของไฟล์แปลภาษาต่าง ๆ ตอนที่คุณวางไฟล์เหล่านั้นในไดเรกทอรี config/locales/ พวกเขาจะพร้อมใช้งานโดยอัตโนมัติ

2.5 กฎการเปลี่ยนรูปของภาษาอื่น ๆ

Rails ช่วยให้คุณสามารถกำหนดกฎการเปลี่ยนรูป (เช่นกฎสำหรับการกำหนดรูปของคำพหูพจน์และคำกริยาในรูปสกุลเดียวกัน) สำหรับภาษาอื่นนอกเหนือจากภาษาอังกฤษ ใน config/initializers/inflections.rb คุณสามารถกำหนดกฎเหล่านี้สำหรับภาษาหลาย ๆ ภาษา ไฟล์เริ่มต้นมีตัวอย่างเริ่มต้นสำหรับการระบุกฎเพิ่มเติมสำหรับภาษาอังกฤษ คุณสามารถทำตามรูปแบบนั้นสำหรับภาษาอื่น ๆ ตามที่คุณเห็นสมควร

2.6 มุมมองท้องถิ่น

เราสมมติว่าคุณมี BooksController ในแอปพลิเคชันของคุณ การกระทำ index จะแสดงเนื้อหาในเทมเพลต app/views/books/index.html.erb เมื่อคุณวาง localized variant ของเทมเพลตนี้: index.es.html.erb ในไดเรกทอรีเดียวกัน Rails จะแสดงเนื้อหาในเทมเพลตนี้เมื่อตั้งค่า locale เป็น :es เมื่อตั้งค่า locale เป็น default locale จะใช้เทมเพลต index.html.erb ทั่วไป (เวอร์ชันข้างหน้าของ Rails อาจนำเสนอการ localiztion automagic นี้ไปยังส่วนทรัพยากรใน public เป็นต้น)

คุณสามารถใช้คุณสมบัตินี้ได้ เช่น เมื่อทำงานกับเนื้อหาสถิตที่มีจำนวนมากซึ่งจะเป็นซับซ้อนในการวางใน YAML หรือ Ruby dictionaries อย่างไรก็ตาม โปรดจำไว้ว่าการเปลี่ยนแปลงใด ๆ ที่คุณต้องการทำในภายหลังกับเทมเพลตจะต้องถูกแพร่กระจายไปยังทั้งหมด

2.7 การจัดระเบียบไฟล์ Locale

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

ตัวอย่างเช่น ไดเรกทอรี config/locales ของคุณอาจมีลักษณะดังนี้:

|-defaults
|---es.yml
|---en.yml
|-models
|---book
|-----es.yml
|-----en.yml
|-views
|---defaults
|-----es.yml
|-----en.yml
|---books
|-----es.yml
|-----en.yml
|---users
|-----es.yml
|-----en.yml
|---navigation
|-----es.yml
|-----en.yml

ด้วยวิธีนี้คุณสามารถแยกชื่อโมเดลและแอตทริบิวต์ของโมเดลจากข้อความภายในวิว และทั้งหมดนี้จาก "ค่าเริ่มต้น" (เช่น รูปแบบวันที่และเวลา) ร้ายอาจารย์อื่น ๆ สำหรับไลบรารี i18n อาจให้วิธีการแยกแยะที่แตกต่างกัน

หมายเหตุ: กลไกการโหลด locale เริ่มต้นใน Rails ไม่โหลดไฟล์ locale ในพจนานุกรมที่ซ้อนกัน เช่นเรามีที่นี่ ดังนั้นเพื่อให้สามารถทำงานได้เราต้องบอก Rails ให้มองหาไกด์เพิ่มเติม:

# config/application.rb
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')]

3 ภาพรวมของคุณลักษณะ API ของ I18n

คุณควรมีความเข้าใจที่ดีในการใช้ไลบรารี i18n และรู้วิธีการนำมาใช้ในแอปพลิเคชัน Rails พื้นฐาน ในบทต่อไป เราจะพิจารณาคุณลักษณะของมันอย่างละเอียดขึ้น

บทนี้จะแสดงตัวอย่างโดยใช้วิธี I18n.translate และ translate view helper method (โดยทำความเข้าใจถึงคุณลักษณะเพิ่มเติมที่ให้โดยเมธอดช่วยเหลือในการมองเห็น)

ครอบคลุมคุณลักษณะเช่นเหล่านี้:

  • การค้นหาแปลภาษา
  • การแทรกข้อมูลในแปลภาษา
  • การกำหนดพหูพจน์ในแปลภาษา
  • การใช้แปลภาษา HTML ที่ปลอดภัย (เฉพาะเมธอดช่วยเหลือในการมองเห็นเท่านั้น)
  • การให้ค่าวันที่เป็นภาษาท้องถิ่น ตัวเลข สกุลเงิน เป็นต้น

3.1 การค้นหาแปลภาษา

3.1.1 การค้นหาพื้นฐาน ขอบเขต และคีย์ที่ซ้อนกัน

แปลภาษาจะถูกค้นหาโดยใช้คีย์ซึ่งสามารถเป็นทั้งสัญลักษณ์และสตริง ดังนั้นการเรียกใช้เหล่านี้เทียบเท่ากัน:

I18n.t :message
I18n.t 'message'

เมธอด translate ยังรับตัวเลือก :scope ซึ่งสามารถมีคีย์เพิ่มเติมหนึ่งหรือมากกว่าที่จะใช้ในการระบุ "เนมสเปซ" หรือขอบเขตสำหรับคีย์แปลภาษา:

I18n.t :record_invalid, scope: [:activerecord, :errors, :messages]

นี้จะค้นหาข้อความ :record_invalid ในข้อความข้อผิดพลาดของ Active Record

นอกจากนี้ ทั้งคีย์และขอบเขตสามารถระบุเป็นคีย์ที่แยกกันด้วยจุดได้ดังนี้:

I18n.translate "activerecord.errors.messages.record_invalid"

ดังนั้นการเรียกใช้เหล่านี้เทียบเท่ากัน: ruby I18n.t 'activerecord.errors.messages.record_invalid' I18n.t 'errors.messages.record_invalid', scope: :activerecord I18n.t :record_invalid, scope: 'activerecord.errors.messages' I18n.t :record_invalid, scope: [:activerecord, :errors, :messages]

3.1.2 ค่าเริ่มต้น

เมื่อมีตัวเลือก :default ถูกกำหนดไว้ ค่าของมันจะถูกส่งกลับหากไม่พบการแปล:

I18n.t :missing, default: 'ไม่มีที่นี่'
# => 'ไม่มีที่นี่'

หากค่า :default เป็นสัญลักษณ์ จะถูกใช้เป็นคีย์และถูกแปลงค่า สามารถกำหนดค่าเริ่มต้นหลายค่าได้ ค่าแรกที่ได้ผลลัพธ์จะถูกส่งกลับ

ตัวอย่างเช่น ต่อไปนี้จะพยายามแปลคีย์ :missing และแปลคีย์ :also_missing หากทั้งสองไม่ได้ผลลัพธ์ จะส่งกลับสตริง "ไม่มีที่นี่":

I18n.t :missing, default: [:also_missing, 'ไม่มีที่นี่']
# => 'ไม่มีที่นี่'

3.1.3 การค้นหาแบบกลุ่มและเนมสเปซ

เพื่อค้นหาแปลหลายรายการในครั้งเดียว สามารถส่งอาร์เรย์ของคีย์ได้:

I18n.t [:odd, :even], scope: 'errors.messages'
# => ["ต้องเป็นเลขคี่", "ต้องเป็นเลขคู่"]

นอกจากนี้ คีย์สามารถแปลงเป็นแฮช (hash) ที่แบ่งกลุ่มแปลได้ (อาจมีการซ้อนกัน) ตัวอย่างเช่น สามารถรับข้อความข้อผิดพลาดทั้งหมดของ Active Record ในรูปแบบแฮชได้ดังนี้:

I18n.t 'errors.messages'
# => {:inclusion=>"ไม่ได้รับอยู่ในรายการ", :exclusion=> ... }

หากต้องการทำตัวแทนที่ในแฮชของแปลภายใน คุณต้องส่ง deep_interpolation: true เป็นพารามิเตอร์ หากคุณมีพจนานุกรมต่อไปนี้:

en:
  welcome:
    title: "ยินดีต้อนรับ!"
    content: "ยินดีต้อนรับสู่ %{app_name}"

แล้วการทำตัวแทนที่ซ้อนกันจะถูกละเว้นโดยไม่ตั้งค่า:

I18n.t 'welcome', app_name: 'ร้านหนังสือ'
# => {:title=>"ยินดีต้อนรับ!", :content=>"ยินดีต้อนรับสู่ %{app_name}"}

I18n.t 'welcome', deep_interpolation: true, app_name: 'ร้านหนังสือ'
# => {:title=>"ยินดีต้อนรับ!", :content=>"ยินดีต้อนรับสู่ร้านหนังสือ"}

3.1.4 การค้นหาแบบ "Lazy"

Rails มีวิธีการสะดวกในการค้นหาภาษาใน views เมื่อคุณมีพจนานุกรมต่อไปนี้:

es:
  books:
    index:
      title: "ชื่อเรื่อง"

คุณสามารถค้นหาค่า books.index.title ภายใน เทมเพลต app/views/books/index.html.erb ได้ดังนี้ (โปรดทราบจุด):

<%= t '.title' %>

หมายเหตุ: การค้นหาแบบ "Lazy" สามารถใช้ได้ในคอนโทรลเลอร์เช่นกัน:

en:
  books:
    create:
      success: สร้างหนังสือแล้ว!

นี้เป็นประโยชน์ในการตั้งค่าข้อความแฟลชเช่น:

class BooksController < ApplicationController
  def create
    # ...
    redirect_to books_url, notice: t('.success')
  end
end

3.2 การกำหนดพหูพจน์

ในภาษาหลายภาษา - รวมถึงภาษาอังกฤษ - มีเพียงสองรูปแบบ คือ พหูพจน์และพหูพจน์ สำหรับสตริงที่กำหนด เช่น "1 ข้อความ" และ "2 ข้อความ" ภาษาอื่น ๆ (อาหรับ, ญี่ปุ่น, รัสเซีย และอื่น ๆ) มีกฎไวยากรณ์ที่แตกต่างกันซึ่งมีรูปแบบพหูพจน์เพิ่มเติมหรือน้อยกว่า รูปแบบพหูพจน์ ดังนั้น I18n API มีคุณสมบัติการกำหนดพหูพจน์ที่ยืดหยุ่น

ตัวแปรการตัดสินใจ :count มีบทบาทพิเศษในที่ว่ามันจะถูกตัดสินใจในการแปลและใช้ในการเลือกพหูพจน์จากการแปลตามกฎพหูพจน์ที่กำหนดในพื้นหลังการตัดสินใจพหูพจน์ ตามค่าเริ่มต้น จะใช้กฎพหูพจน์ภาษาอังกฤษเท่านั้น

I18n.backend.store_translations :en, inbox: {
  zero: 'ไม่มีข้อความ', # ไม่จำเป็น
  one: '1 ข้อความ',
  other: '%{count} ข้อความ'
}
I18n.translate :inbox, count: 2
# => '2 ข้อความ'

I18n.translate :inbox, count: 1
# => '1 ข้อความ'

I18n.translate :inbox, count: 0
# => 'ไม่มีข้อความ'

อัลกอริทึมสำหรับการพหุนามใน :en มีความง่ายดังนี้:

lookup_key = :zero if count == 0 && entry.has_key?(:zero)
lookup_key ||= count == 1 ? :one : :other
entry[lookup_key]

การแปลที่ระบุว่า :one ถือเป็นรูปเดียว และ :other ถูกใช้เป็นรูปพหุนาม หากจำนวนเป็นศูนย์ และมีรายการ :zero อยู่ จะใช้แทน :other แทน

หากการค้นหาคีย์ไม่ส่งคืน Hash ที่เหมาะสมสำหรับการพหุนาม จะเกิดข้อยกเว้น I18n::InvalidPluralizationData

3.2.1 กฎเฉพาะของภาษา

แพ็กเกจ I18n มี Pluralization backend ที่ใช้เพื่อเปิดใช้กฎเฉพาะของภาษา รวมกับ Simple backend แล้ว เพิ่มอัลกอริทึมพหุนามของภาษาที่แปลงไว้ใน translation store เป็น i18n.plural.rule

I18n::Backend::Simple.include(I18n::Backend::Pluralization)
I18n.backend.store_translations :pt, i18n: { plural: { rule: lambda { |n| [0, 1].include?(n) ? :one : :other } } }
I18n.backend.store_translations :pt, apples: { one: 'one or none', other: 'more than one' }

I18n.t :apples, count: 0, locale: :pt
# => 'one or none'

หรือใช้แพ็กเสริมแยกออกมา rails-i18n เพื่อให้ได้กฎพหุนามของภาษาที่ครบถ้วนมากขึ้น

3.3 การตั้งค่าและส่งต่อภาษา

ภาษาสามารถตั้งค่าเป็น pseudo-globally ที่ I18n.locale (ซึ่งใช้ Thread.current เช่นเดียวกับ Time.zone เป็นต้น) หรือสามารถส่งผ่านเป็นตัวเลือกให้กับ #translate และ #localize ได้

หากไม่มีการส่งภาษา จะใช้ I18n.locale:

I18n.locale = :de
I18n.t :foo
I18n.l Time.now

การส่งภาษาโดยตรง:

I18n.t :foo, locale: :de
I18n.l Time.now, locale: :de

I18n.locale มีค่าเริ่มต้นเป็น I18n.default_locale ซึ่งมีค่าเริ่มต้นเป็น :en สามารถตั้งค่าภาษาเริ่มต้นได้ดังนี้:

I18n.default_locale = :de

3.4 การใช้งานการแปลภาษาที่ปลอดภัยสำหรับ HTML

คีย์ที่มี '_html' ต่อท้ายและคีย์ที่ชื่อ 'html' ถูกทำเครื่องหมายว่าปลอดภัยสำหรับ HTML โดยเมื่อใช้ในมุมมอง HTML จะไม่ถูกหลีกเลี่ยง

# config/locales/en.yml
en:
  welcome: <b>welcome!</b>
  hello_html: <b>hello!</b>
  title:
    html: <b>title!</b>
<!-- app/views/home/index.html.erb -->
<div><%= t('welcome') %></div>
<div><%= raw t('welcome') %></div>
<div><%= t('hello_html') %></div>
<div><%= t('title.html') %></div>

การตัดคำตามต้องการจะถูกทำเครื่องหมายตามที่จำเป็น ตัวอย่างเช่น กำหนดให้:

en:
  welcome_html: "<b>Welcome %{username}!</b>"

คุณสามารถส่งชื่อผู้ใช้ที่ถูกตั้งค่าโดยผู้ใช้ได้อย่างปลอดภัย:

<%# นี่เป็นปลอดภัย มันจะถูกตัดคำตามความจำเป็น %>
<%= t('welcome_html', username: @current_user.username) %>

สตริงที่ปลอดภัยอย่างอื่น ๆ จะถูกตัดคำตามต้องการ

หมายเหตุ: การแปลงอัตโนมัติเป็น HTML safe ข้อความแปลเท่านั้นที่สามารถใช้ได้จากเมธอดช่วย translate (หรือ t) นี้ สามารถใช้งานได้ในมุมมองและคอนโทรลเลอร์

i18n demo HTML safe

3.5 การแปลภาษาสำหรับโมเดล Active Record

คุณสามารถใช้เมธอด Model.model_name.human และ Model.human_attribute_name(attribute) เพื่อค้นหาแปลภาษาสำหรับโมเดลและชื่อแอตทริบิวต์ของคุณได้อย่างโปร่งใส

ตัวอย่างเช่นเมื่อคุณเพิ่มแปลภาษาต่อไปนี้:

en:
  activerecord:
    models:
      user: Customer
    attributes:
      user:
        login: "Handle"
      # จะแปลงแอตทริบิวต์ User "login" เป็น "Handle"

จากนั้น User.model_name.human จะคืนค่าเป็น "Customer" และ User.human_attribute_name("login") จะคืนค่าเป็น "Handle"

คุณยังสามารถตั้งค่ารูปพหุนามสำหรับชื่อโมเดลได้อีกด้วย โดยเพิ่มดังนี้:

en:
  activerecord:
    models:
      user:
        one: Customer
        other: Customers

แล้ว User.model_name.human(count: 2) จะคืนค่าเป็น "ลูกค้า" ด้วย count: 1 หรือโดยไม่ระบุพารามิเตอร์จะคืนค่าเป็น "ลูกค้า"

ในกรณีที่คุณต้องการเข้าถึงแอตทริบิวต์ที่ซ้อนกันภายในโมเดลที่กำหนด คุณควรซ้อนเหล่านี้ภายใต้ model/attribute ที่ระดับโมเดลของไฟล์แปลของคุณ:

en:
  activerecord:
    attributes:
      user/role:
        admin: "ผู้ดูแลระบบ"
        contributor: "ผู้ร่วมสนContributor"

แล้ว User.human_attribute_name("role.admin") จะคืนค่าเป็น "ผู้ดูแลระบบ"

หมายเหตุ: หากคุณกำลังใช้คลาสที่รวม ActiveModel และไม่สืบทอดจาก ActiveRecord::Base ให้แทนที่ activerecord ด้วย activemodel ในเส้นทางคีย์ด้านบน

3.5.1 ขอบเขตข้อความข้อผิดพลาด

ข้อความข้อผิดพลาดในการตรวจสอบของ Active Record ยังสามารถแปลงแปลงได้อย่างง่ายดาย Active Record ให้คุณใช้งานเนมสเปซที่คุณสามารถวางแปลงข้อความของคุณได้เพื่อให้ได้ข้อความและการแปลงแตกต่างสำหรับโมเดลที่แตกต่างกัน แอตทริบิวต์ และ/หรือการตรวจสอบที่แตกต่างกัน นอกจากนี้ยังรองรับการสืบทอดตารางเดียวเองอย่างโปร่งใส

นี้จะให้คุณมีวิธีที่มีประสิทธิภาพในการปรับแต่งข้อความข้อผิดพลาดให้เหมาะสมกับความต้องการของแอปพลิเคชันของคุณ

พิจารณาโมเดล User ที่มีการตรวจสอบสำหรับแอตทริบิวต์ชื่อดังนี้:

class User < ApplicationRecord
  validates :name, presence: true
end

คีย์สำหรับข้อความข้อผิดพลาดในกรณีนี้คือ :blank Active Record จะค้นหาคีย์นี้ในเนมสเปซต่อไปนี้:

activerecord.errors.models.[model_name].attributes.[attribute_name]
activerecord.errors.models.[model_name]
activerecord.errors.messages
errors.attributes.[attribute_name]
errors.messages

ดังนั้นในตัวอย่างของเราจะลองค้นหาคีย์ต่อไปนี้ตามลำดับนี้และคืนค่าผลลัพธ์แรก:

activerecord.errors.models.user.attributes.name.blank
activerecord.errors.models.user.blank
activerecord.errors.messages.blank
errors.attributes.name.blank
errors.messages.blank

เมื่อโมเดลของคุณใช้การสืบทอดเพิ่มเติม ข้อความจะถูกค้นหาในลำดับการสืบทอด

ตัวอย่างเช่น คุณอาจมีโมเดล Admin ที่สืบทอดจาก User:

class Admin < User
  validates :name, presence: true
end

แล้ว Active Record จะค้นหาข้อความตามลำดับนี้:

activerecord.errors.models.admin.attributes.name.blank
activerecord.errors.models.admin.blank
activerecord.errors.models.user.attributes.name.blank
activerecord.errors.models.user.blank
activerecord.errors.messages.blank
errors.attributes.name.blank
errors.messages.blank

ด้วยวิธีนี้คุณสามารถให้แปลงแปลงพิเศษสำหรับข้อความข้อผิดพลาดต่างๆ ที่จุดต่างๆ ในโมเดลที่สืบทอดและในแอตทริบิวต์ โมเดล หรือขอบเขตเริ่มต้น

3.5.2 การแทรกข้อความข้อผิดพลาด

ชื่อโมเดลที่แปลแล้ว ชื่อแอตทริบิวต์ที่แปลแล้ว และค่าที่แปลแล้วจะมีอยู่เสมอสำหรับการแทรกข้อความเป็น model attribute และ value ตามลำดับ

ดังนั้น เช่น แทนที่ข้อความข้อผิดพลาดเริ่มต้น "cannot be blank" คุณสามารถใช้ชื่อแอตทริบิวต์เช่นนี้: "กรุณากรอก %{attribute} ของคุณ".

  • count ถ้ามีอยู่ สามารถใช้สำหรับการกำหนดพหูพจน์:
การตรวจสอบ พร้อมตัวเลือก ข้อความ การแทรกข้อความ
confirmation - :confirmation attribute
acceptance - :accepted -
presence - :blank -
absence - :present -
length :within, :in :too_short count
length :within, :in :too_long count
length :is :wrong_length count
length :minimum :too_short count
length :maximum :too_long count
uniqueness - :taken -
format - :invalid -
inclusion - :inclusion -
exclusion - :exclusion -
associated - :invalid -
non-optional association - :required -
numericality - :not_a_number -
numericality :greater_than :greater_than count
numericality :greater_than_or_equal_to :greater_than_or_equal_to count
numericality :equal_to :equal_to count
numericality :less_than :less_than count
numericality :less_than_or_equal_to :less_than_or_equal_to count
numericality :other_than :other_than count
numericality :only_integer :not_an_integer -
numericality :in :in count
numericality :odd :odd -
numericality :even :even -
comparison :greater_than :greater_than count
comparison :greater_than_or_equal_to :greater_than_or_equal_to count
comparison :equal_to :equal_to count
comparison :less_than :less_than count
comparison :less_than_or_equal_to :less_than_or_equal_to count
comparison :other_than :other_than count

3.6 การแปลสำหรับหัวข้ออีเมล Action Mailer

หากคุณไม่ส่งหัวข้อให้กับเมธอด mail Action Mailer จะพยายามหาหัวข้อในการแปลของคุณ การค้นหาที่ทำจะใช้รูปแบบ <mailer_scope>.<action_name>.subject เพื่อสร้างคีย์

# user_mailer.rb
class UserMailer < ActionMailer::Base
  def welcome(user)
    #...
  end
end
en:
  user_mailer:
    welcome:
      subject: "ยินดีต้อนรับสู่ Rails Guides!"

ในการส่งพารามิเตอร์ไปยังการตัดคำใช้เมธอด default_i18n_subject บนเมลเลอร์

# user_mailer.rb
class UserMailer < ActionMailer::Base
  def welcome(user)
    mail(to: user.email, subject: default_i18n_subject(user: user.name))
  end
end
en:
  user_mailer:
    welcome:
      subject: "%{user}, ยินดีต้อนรับสู่ Rails Guides!"

3.7 ภาพรวมของเมธอดอื่น ๆ ที่มีการให้การสนับสนุน I18n

Rails ใช้สตริงคงที่และการแปลอื่น ๆ เช่นสตริงรูปแบบและข้อมูลรูปแบบอื่น ๆ ในหลายๆ เมธอดช่วยเหลือ นี่คือภาพรวมสั้นๆ

3.7.1 เมธอดช่วยเหลือ Action View

  • distance_of_time_in_words แปลและทำให้พหูพจน์ผลลัพธ์และตัดคำตัวเลขวินาที นาที ชั่วโมง และอื่นๆ ดูการแปลที่ datetime.distance_in_words

  • datetime_select และ select_month ใช้ชื่อเดือนที่แปลแล้วสำหรับการเติมค่าในแท็ก select ที่ได้รับผลลัพธ์ ดูการแปลที่ date.month_names สำหรับการแปล datetime_select ยังค้นหาตัวเลือก order จาก date.order (ยกเว้นว่าคุณจะส่งตัวเลือกไปโดยชัดเจน) ช่วยเลือกวันที่ทั้งหมดแปลคำถามโดยใช้การแปลในขอบเขต datetime.prompts ถ้ามี

  • เมธอด number_to_currency, number_with_precision, number_to_percentage, number_with_delimiter, และ number_to_human_size ใช้การตั้งค่ารูปแบบตัวเลขที่อยู่ในขอบเขต number

3.7.2 เมธอด Active Model

  • model_name.human และ human_attribute_name ใช้การแปลสำหรับชื่อโมเดลและชื่อแอตทริบิวต์ถ้ามีในขอบเขต activerecord.models พวกเขายังสนับสนุนการแปลสำหรับชื่อคลาสที่สืบทอด (เช่นสำหรับใช้กับ STI) ตามที่อธิบายไว้ด้านบนใน "ขอบเขตข้อความข้อผิดพลาด"

  • ActiveModel::Errors#generate_message (ซึ่งใช้ในการตรวจสอบความถูกต้องของ Active Model แต่อาจใช้ด้วยตนเอง) ใช้ model_name.human และ human_attribute_name (ดูด้านบน) นอกจากนี้ยังแปลคำผิดพลาดและสนับสนุนการแปลสำหรับชื่อคลาสที่สืบทอดตามที่อธิบายไว้ด้านบนใน "ขอบเขตข้อความข้อผิดพลาด"

  • ActiveModel::Error#full_message และ ActiveModel::Errors#full_messages เติมชื่อแอตทริบิวต์ในข้อความผิดพลาดโดยใช้รูปแบบที่ค้นหาจาก errors.format (ค่าเริ่มต้น: "%{attribute} %{message}") หากต้องการปรับแต่งรูปแบบเริ่มต้นให้เขียนทับในไฟล์โลเคลล์ของแอป หากต้องการปรับแต่งรูปแบบตามโมเดลหรือแอตทริบิวต์ ดูที่ config.active_model.i18n_customize_full_message

3.7.3 เมธอด Active Support

  • Array#to_sentence ใช้การตั้งค่ารูปแบบตามที่กำหนดในขอบเขต support.array

4 วิธีการเก็บการแปลที่กำหนดเอง

Backend ที่เรียบง่ายที่ส่งพร้อม Active Support ช่วยให้คุณเก็บการแปลได้ทั้งในรูปแบบ Ruby และรูปแบบ YAML.2

ตัวอย่างของแปลที่ให้โดยใช้ Ruby Hash อาจมีดังนี้:

{
  pt: {
    foo: {
      bar: "baz"
    }
  }
}

ไฟล์ YAML ที่เทียบเท่าจะมีลักษณะดังนี้:

pt:
  foo:
    bar: baz

เห็นได้ว่าในทั้งสองกรณีคีย์ระดับบนสุดคือ locale :foo เป็นคีย์ของเนมสเปซและ :bar เป็นคีย์สำหรับการแปล "baz"

นี่คือตัวอย่าง "จริง" จากไฟล์แปล YAML ของ Active Support en.yml:

en:
  date:
    formats:
      default: "%Y-%m-%d"
      short: "%b %d"
      long: "%B %d, %Y"

ดังนั้นการค้นหาที่เหมือนกันต่อไปนี้จะคืนรูปแบบวันที่ :short "%b %d": ruby I18n.t 'date.formats.short' I18n.t 'formats.short', scope: :date I18n.t :short, scope: 'date.formats' I18n.t :short, scope: [:date, :formats]

ทั่วไปแล้วเราแนะนำให้ใช้ YAML เป็นรูปแบบในการเก็บข้อมูลแปลภาษา อย่างไรก็ตาม มีกรณีบางกรณีที่คุณต้องการเก็บ Ruby lambdas เป็นส่วนหนึ่งของข้อมูลภาษา ตัวอย่างเช่นสำหรับรูปแบบวันที่พิเศษ

5 ปรับแต่งการตั้งค่า I18n ของคุณ

5.1 การใช้ Backend ที่แตกต่างกัน

ด้วยเหตุผลหลายประการ Backend ที่จัดส่งพร้อมกับ Active Support ทำเพียง "สิ่งที่ง่ายที่สุดที่สามารถทำได้" สำหรับ Ruby on Rails3 ... ซึ่งหมายความว่ามันสามารถทำงานได้เฉพาะภาษาอังกฤษและอาจมีผลข้างเคียงที่เกี่ยวข้องกับภาษาที่คล้ายกันมาก นอกจากนี้ Backend ที่เรียบง่ายสามารถอ่านแปลงานแปลงได้เท่านั้นแต่ไม่สามารถเก็บไว้ในรูปแบบใด ๆ ได้

แต่นั่นไม่ได้หมายความว่าคุณต้องติดอยู่กับข้อจำกัดเหล่านี้ แต่ Ruby I18n gem ทำให้ง่ายมากที่จะแทนที่การดำเนินการ Backend ที่เรียบง่ายด้วยสิ่งอื่นที่เหมาะสมกับความต้องการของคุณ โดยการส่ง backend instance ไปยัง setter I18n.backend=

ตัวอย่างเช่นคุณสามารถแทนที่ Backend ที่เรียบง่ายด้วย Chain backend เพื่อเชื่อมต่อ backend หลายรายการเข้าด้วยกัน ซึ่งเป็นประโยชน์เมื่อคุณต้องการใช้การแปลภาษามาตรฐานกับ Backend ที่เรียบง่าย แต่เก็บการแปลภาษาแอปพลิเคชันที่กำหนดเองในฐานข้อมูลหรือ backend อื่น ๆ

ด้วย Chain backend คุณสามารถใช้ Active Record backend และย้อนกลับไปยัง Simple backend (ค่าเริ่มต้น):

I18n.backend = I18n::Backend::Chain.new(I18n::Backend::ActiveRecord.new, I18n.backend)

5.2 การใช้ Exception Handlers ที่แตกต่างกัน

API ของ I18n กำหนดข้อยกเว้นต่อไปนี้ที่จะถูกเรียกขึ้นโดย backend เมื่อเกิดเงื่อนไขที่ไม่คาดคิด:

ข้อยกเว้น เหตุผล
I18n::MissingTranslationData ไม่พบการแปลสำหรับคีย์ที่ร้องขอ
I18n::InvalidLocale ภาษาที่ตั้งค่าเป็น I18n.locale ไม่ถูกต้อง (เช่น nil)
I18n::InvalidPluralizationData มีการส่งตัวเลือกนับแต่ข้อมูลแปลภาษาไม่เหมาะสมสำหรับพหูพจน์
I18n::MissingInterpolationArgument การแปลคาดหวังอาร์กิวเมนต์ที่ยังไม่ได้ถูกส่ง
I18n::ReservedInterpolationKey การแปลมีชื่อตัวแปรอินเตอร์โพเลชันที่สงวนไว้ (เช่น: scope, default)
I18n::UnknownFileType backend ไม่รู้จักวิธีการจัดการประเภทไฟล์ที่เพิ่มเข้าไปใน I18n.load_path

5.2.1 การปรับแต่งวิธีการจัดการ I18n::MissingTranslationData

หาก config.i18n.raise_on_missing_translations เป็น true ข้อผิดพลาด I18n::MissingTranslationData จะถูกเรียกขึ้น คุณควรเปิดใช้งานสิ่งนี้ในสภาพแวดล้อมการทดสอบ เพื่อให้คุณสามารถตรวจจับสถานที่ที่ขาดหายไปของการแปลได้

หาก config.i18n.raise_on_missing_translations เป็น false (ค่าเริ่มต้นในสภาพแวดล้อมทั้งหมด) ข้อผิดพลาดของข้อยกเว้นจะถูกพิมพ์ออกมา ซึ่งประกอบด้วยคีย์/สโคปที่ขาดหายไปเพื่อให้คุณสามารถแก้ไขโค้ดของคุณ

หากคุณต้องการปรับแต่งพฤติกรรมนี้ได้อีกต่อไป คุณควรตั้งค่า config.i18n.raise_on_missing_translations = false แล้วดำเนินการสร้าง I18n.exception_handler ที่กำหนดเอง ตัวจัดการข้อยกเว้นที่กำหนดเองสามารถเป็น proc หรือคลาสที่มีเมธอด call:

# config/initializers/i18n.rb
module I18n
  class RaiseExceptForSpecificKeyExceptionHandler
    def call(exception, locale, key, options)
      if key == "special.key"
        "translation missing!" # return this, don't raise it
      elsif exception.is_a?(MissingTranslation)
        raise exception.to_exception
      else
        raise exception
      end
    end
  end
end

I18n.exception_handler = I18n::RaiseExceptForSpecificKeyExceptionHandler.new

นี้จะเรียกข้อยกเว้นทั้งหมดในทางเดียวกันกับตัวจัดการเริ่มต้น ยกเว้นในกรณีของ I18n.t("special.key") การแปล API I18n ที่อธิบายในคู่มือนี้มีวัตถุประสงค์หลักในการแปลสตริงของอินเตอร์เฟซ หากคุณต้องการแปลเนื้อหาของโมเดล (เช่นบทความบล็อก) คุณจะต้องใช้วิธีการที่แตกต่างเพื่อช่วยในการทำเช่นนี้

มี Gems หลายตัวที่ช่วยในการแปลเนื้อหาดังนี้:

  • Mobility: สนับสนุนการเก็บรักษาการแปลในรูปแบบหลายรูปแบบ เช่น ตารางแปลภาษา คอลัมน์ JSON (PostgreSQL) เป็นต้น
  • Traco: คอลัมน์ที่สามารถแปลได้เก็บไว้ในตารางโมเดลเอง

6 สรุป

ในจุดนี้คุณควรมีภาพรวมที่ดีเกี่ยวกับวิธีการสนับสนุน I18n ใน Ruby on Rails และพร้อมที่จะเริ่มต้นการแปลโปรเจกต์ของคุณ

7 การมีส่วนร่วมใน Rails I18n

การสนับสนุน I18n ใน Ruby on Rails ถูกนำเสนอในเวอร์ชัน 2.2 และยังคงพัฒนาอย่างต่อเนื่อง โครงการนี้ปฏิบัติตามแบบฉบับการพัฒนา Ruby on Rails ที่ดีโดยพัฒนาแนวทางใน Gems และแอปพลิเคชันจริงก่อน และจากนั้นเลือกเฉพาะคุณสมบัติที่ดีที่สุดและมีประโยชน์ที่สุดสำหรับการรวมเข้ากับคอร์

ดังนั้นเราขอเชิญทุกคนที่จะทดลองใช้ไอเดียและคุณสมบัติใหม่ใน Gems หรือไลบรารีอื่น ๆ และทำให้พวกเขาเป็นที่ใช้งานได้สำหรับชุมชน (อย่าลืมประกาศงานของคุณใน mailing list ของเรา!)

หากคุณพบว่าภาษาของคุณไม่มีในเรื่องตัวอย่างข้อมูลแปล (translations) ของเราสำหรับ Ruby on Rails กรุณา fork รีพอสิทธิ์ และเพิ่มข้อมูลของคุณ แล้วส่ง pull request มาให้เรา

8 ทรัพยากร

  • กลุ่ม Google: rails-i18n - กลุ่มสมาชิกทางอีเมลของโครงการ
  • GitHub: rails-i18n - ที่เก็บรหัสและติดตามปัญหาสำหรับโครงการ rails-i18n ที่สำคัญที่สุดคุณสามารถค้นหา ตัวอย่างการแปล สำหรับ Rails ที่ควรทำงานสำหรับแอปพลิเคชันของคุณในกรณีส่วนใหญ่
  • GitHub: i18n - ที่เก็บรหัสและติดตามปัญหาสำหรับ gem i18n

9 ผู้เขียน

10 เชิงอรรถ

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

2 แบ็กเอนด์อื่นอาจอนุญาตหรือต้องการให้ใช้รูปแบบอื่น เช่น แบ็กเอนด์ GetText อาจอนุญาตให้อ่านไฟล์ GetText

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

ข้อเสนอแนะ

คุณสามารถช่วยปรับปรุงคุณภาพของคู่มือนี้ได้

กรุณาช่วยเพิ่มเติมหากพบข้อผิดพลาดหรือข้อผิดพลาดทางความจริง เพื่อเริ่มต้นคุณสามารถอ่านส่วน การสนับสนุนเอกสาร ของเราได้

คุณอาจพบเนื้อหาที่ไม่สมบูรณ์หรือเนื้อหาที่ไม่ได้อัปเดต กรุณาเพิ่มเอกสารที่ขาดหายไปสำหรับเนื้อหาหลัก โปรดตรวจสอบ Edge Guides ก่อนเพื่อตรวจสอบ ว่าปัญหาได้รับการแก้ไขหรือไม่ในสาขาหลัก ตรวจสอบ คู่มือแนวทาง Ruby on Rails เพื่อดูรูปแบบและกฎเกณฑ์

หากคุณพบข้อผิดพลาดแต่ไม่สามารถแก้ไขได้เอง กรุณา เปิดปัญหา.

และสุดท้าย การสนทนาใด ๆ เกี่ยวกับ Ruby on Rails เอกสารยินดีต้อนรับที่สุดใน เว็บบอร์ดอย่างเป็นทางการของ Ruby on Rails.