วิธีการทำ React 2 ภาษาด้วย React i18n-next
สวัสดีครับ วันนี้ผมมีตัวอย่างการทำเว็บ 2 ภาษา ด้วย React กันครับ เผื่อว่าบางคนเวลาทำเว็บด้วย React แล้วเวลาใช้งานฟังค์ชัน 2 ภาษา อาจจะต้องส่ง key lang
แนบไปที่ header หรือว่าทุกๆ request แล้วให้ทางฝั่ง Server นั้นคอย handle แต่ว่าบทความนี้ไม่ใช่แบบนั้น แต่จะเป็นการเปลี่ยนภาษาทางฝั่ง Client ไปเลย ด้วยพระเอกของงานนี้ นั่นคือ React i18next นั่นเอง ตัวอย่างการทำเว็บ 2 ภาษาด้วย React i18n Next
Step 1 : Create Project
เริ่มต้นสร้างโปรเจ็คขึ้นมาใหม่เลย ซึ่งในตัวอย่างนี้ผมจะใช้ Create React App
ในการสร้างเพราะมันง่าย ไม่ต้อง Setup อะไรให้มันยุ่งยากเท่าไหร่
npx creact-react-app learn-react-i18n
cd learn-react-i18n
npm start
สำหรับใครไม่รู้จัก หรือไม่เคยสร้างโปรเจ็คด้วย Create React App เชิญอ่านเพิ่มเติม Create React App
จะต้องได้หน้าเว็บแบบนี้ แสดงว่าเรามาถูกทางแล้ว
Step 2 : Setup i18n
ต่อมาทำการติดตั้ง Dependencies ต่างๆที่ใช้กับ React i18next กัน
npm install i18next react-i18next i18next-xhr-backend
i18next
: ตัว Library หลักreact-i18next
: ตัว Library ที่แปลงมาเป็นเวอร์ชันที่ใช้สำหรับ Reacti18next-xhr-backend
: เป็นคล้ายๆตัว Controller ที่มันจะโหลดไฟล์ locale JSON ให้เราและทำการ parse ข้อมูล
ต่อมาทำการสร้างไฟล์ i18n.js
ขึ้นมา (ที่เดียวกันกับ App.js
)
import i18n from 'i18next'
import XHR from 'i18next-xhr-backend'
import { reactI18nextModule } from 'react-i18next'
i18n
.use(XHR)
.use(reactI18nextModule)
.init({
fallbackLng: 'th',
ns: ['trans'],
defaultNS: 'trans',
debug: true,
interpolation: {
escapeValue: false
},
react: {
wait: true
}
})
export default i18n
และก็ขั้นตอนสุดท้ายในการ Setup ก็คือทำการเพิ่มไฟล์ locale ซึ่ง default มันคือ locales/lang/trans.json
ซึ่งในบทความจะใช้ 2 ภาษาคือ ไทยและอังกฤษ ก็เลยสร้าง 2 ไฟล์คือ
/public/locales/en/trans.json
: สำหรับข้อมูลภาษาอังกฤษ/public/locales/th/trans.json
: สำหรับข้อมูลภาษาไทย
ตัวอย่างไฟล์ en/trans.json
{
"title": "React i18n",
"subtitle": "React i18n with i18next Tutorial",
"lang_text": "Please select language : ",
"lang_en": "English",
"lang_th": "Thai",
"header": "Example of React i18next",
"content": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Possimus nisi perferendis repellat consequatur commodi esse, delectus, cum in, ab illo maxime similique maiores culpa exercitationem ullam mollitia, ad ratione inventore?",
"welcome_message": "Hello, {{name}}. Welcome to {{website}}!",
"read_more": "Read more",
"post": "Post :",
"source_code": "Source Code :"
}
ตัวอย่างไฟล์ th/trans.json
{
"title": "React i18n",
"subtitle": "React i18n with i18next Tutorial",
"lang_text": "กรุณาเลือกภาษา : ",
"lang_en": "ภาษาอังกฤษ",
"lang_th": "ภาษาไทย",
"header": "ตัวอย่างการใช้งาน React i18next",
"content": "Lorem Ipsum คือ เนื้อหาจำลองแบบเรียบๆ ที่ใช้กันในธุรกิจงานพิมพ์หรืองานเรียงพิมพ์ มันได้กลายมาเป็นเนื้อหาจำลองมาตรฐานของธุรกิจดังกล่าวมาตั้งแต่ศตวรรษที่ 16",
"welcome_message": "สวัสดี, {{name}}. ยินดีต้อนรับสู่เว็บไซต์ {{website}}!",
"read_more": "อ่านบทความต่อ",
"post": "บทความ :",
"source_code": "ซอร์สโค๊ด :"
}
Step 3 : with High Order Function (HOC)
การใช้งาน i18next แบบง่ายสุด ก็คือทำผ่าน (HOC) (High Order Function)
วิธีการก็คือ เมื่อเรายัด component ผ่าน HOC แล้ว เราก็จะสามารถเรียก function t
ที่เป็น function ของ i18next ที่ให้เราสามารถเรียกใช้งานได้เลยผ่าน Props ตัวอย่าง เช่น
const { translate } from 'react-i18next'
const App = ({ t }) => (
<div>
<h1>{t('KEY_NAME')}</h1>
</div>
)
export default translate()(App)
Step 4 : with Render Props
การใช้งาน i18next อีกแบบหนึ่งก็คือ การใช้งานผ่าน Render ผ่านตัว instance ของ i18next นั่นเอง
วิธีการก็คือเราต้องสร้าง children ภายใน <I18n>
เป็นฟังค์ชัน เพื่อทำการ render ประมาณนี้
import { I18n } from 'react-i18next'
const App = () => (
<I18n>
<MyApp />
</I18n>
)
const MyApp = ({ t }) => (
<div>
<h1>{t('KEY_NAME')}</h1>
</div>
)
Step 5 : Interpolate
ต่อมาการใช้งาน Interpolate หรือก็คือ Dynamic Message ตัวอย่าง เช่น เรา อยากให้มัน translate คำ โดยเปลี่ยนแปลงค่าตามตัวแปรที่เราต้องการ เช่น
ภาษาอังกฤษ
Hello World {{currentUser}}
ภาษาไทย
สวัสดี {{currentUser}}
ซึ่ง มันแปลให้อยู่แล้ว ในคำทักทาย แต่ว่าตัว currentUser
มันจะไม่แปลให้ และจะเปลี่ยนขึ้นอยู่กับว่า เราจะส่ง ตัวแปรอะไรไป และวิธีการเรียกใช้งานก็แค่ ส่ง Object พร้อม key เดียวกันกับไฟล์ locale ไป ใน argument ที่ 2 ดังเช่น
t('KEY_NAME', { currentUser: 'John Doe' })
ซึ่งผลลัพธ์ก็จะได้เป็น
Hello World John Doe
สวัสดี John Doe
แค่นี้เอง ง่ายๆ
ซึ่ง Default ตัว interpolate จะดู key ตาม format
{{}}
แต่เราสามารถ custom ได้
Step 6 : Implement App.js
ต่อมา หลังจากดูตัวอย่างไปหลายๆแบบละ คราวนี้จะมาลองทำการ Implement App จริงๆ ต่อจาก Step ที่ 2 หลังจากที่เราได้ไฟล์ locales ของเราแล้ว ถัดมาคือการเปลี่ยนไฟล์ App.js
ซึ่งผมทำการ Custom ขึ้นมาดังนี้
import React from 'react'
import i18n from './i18n'
import { translate } from 'react-i18next'
import './App.css'
const App = ({ t }) => (
<div className="App">
<section className="hero is-info">
<div className="hero-body has-text-centered">
<div className="container">
<h1 className="title">{t('title')}</h1>
<h2>{t('subtitle')}</h2>
</div>
</div>
</section>
<div className="language-button-section">
<span>{t('lang_text')}</span>
<button
className="button"
onClick={() => {
i18n.changeLanguage('th')
}}
>
{t('lang_th')}
</button>
<button
className="button"
onClick={() => {
i18n.changeLanguage('en')
}}
>
{t('lang_en')}
</button>
</div>
<div className="container columns">
<div className="column is-8 is-offset-4">
<div className="box normal-content">
<h3 className="title">{t('header')}</h3>
<p>{t('content')}</p>
</div>
<div className="box interpolate-content">
<p>
{t('welcome_message', {
name: 'Chai Phonbopit',
website: 'devahoy.com'
})}
</p>
</div>
<div className="box info">
<h3 className="title">{t('read_more')}</h3>
<ul>
<li>
<strong>{t('post')}</strong>{' '}
<a
href="https://devahoy.com/blog/2018/04/getting-started-with-react-i18next/"
target="_blank"
>
วิธีการทำ React 2 ภาษาด้วย React i18n-next
</a>
</li>
<li>
<strong>{t('source_code')}</strong>{' '}
<a
href="https://github.com/Devahoy/hello-react-i18next"
target="_blank"
>
hello-react-i18next
</a>
</li>
</ul>
</div>
</div>
</div>
<footer className="footer">
<div className="container">
<div className="content has-text-centered">
<p>
Powered by{' '}
<a href="https://devahoy.com" target="_blank">
devahoy.com
</a>
</p>
</div>
</div>
</footer>
</div>
)
export default translate()(App)
และแก้ไฟล์ public/index.html
ซะหน่อย เนื่องจากผมใช้ Bulma มาเป็น CSS Framework
<head>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.2/css/bulma.min.css"
/>
<link
href="https://fonts.googleapis.com/css?family=Montserrat"
rel="stylesheet"
/>
</head>
อธิบายเพิ่มเติมจาก App.js
ซักนิด
t('KEY_NAME')
: ทำการ translate ตาม key ที่มีในไฟล์ locale ของเราt('KEY_NAME', { key: value })
: ทำการ translate แบบ Dynamic โดยเปลี่ยนค่า template เป็น key ของเราi18n.changeLanguage()
: คือ method ที่เราใช้สำหรับเปลี่ยนภาษา โดยรับ เป็น locale เช่นen
,th
หรือde
เป็นต้นtranslate()(App)
: เป็น HOC ที่ทำให้เราสามารถเรียกใช้ props ของ i18next ได้เลย
ซึ่งจะบอกว่าตัวอย่างบทความนี้ก็เป็นเพียงแค่ Basic Example เท่านั้น มันยังสามารถ Custom หรือเรียกใช้ได้หลายๆแบบ เช่น ใช้ไฟล์ template หลายๆไฟล์ ทำยังไง แต่ละ Component จะใช้ locale แยกยังไง? หุ้ม i18nProvider
ไปเลยดีไหม หรือปรับเปลี่ยน template ในการทำ interpolation ก้ได้ เช่นจากใช้ {{}}
อาจจะเปลี่ยนเป็น []
หรือ ภายใน %%
อะไรก็ว่าไป
สุดท้าย Source Code ของบทความนี้ครับ
Reference
- Authors
- Name
- Chai Phonbopit
- Website
- @Phonbopit