ง่าย i18n สำหรับ next.js +10
ปลั๊กอินถัดไป + I18N API
บันทึก
เรากำลังทำงานกับเวอร์ชัน 3.0.0 ของ Translate ต่อไป ในช่วงไม่กี่เดือนที่ผ่านมาเราให้ความสำคัญกับ Brisa ดังนั้นจึงเป็นเวลานานตั้งแต่การเปิดตัวครั้งสุดท้าย แต่เรายังไม่ลืมเกี่ยวกับการแปลครั้งต่อไป เรากำลังทำงานกับเวอร์ชันใหม่ที่จะนำการปรับปรุงและคุณสมบัติใหม่มากมาย เราตื่นเต้นมากที่จะแบ่งปันกับพวกคุณทุกคน

เป้าหมายหลักของห้องสมุดนี้คือการแปลให้ง่ายที่สุดเท่าที่จะเป็นไปได้ในสภาพแวดล้อมถัดไป
TRANSLATE ถัดไปมีสองส่วน: Next.js Plugin + I18N API
คุณสมบัติ

ในไฟล์กำหนดค่าคุณระบุแต่ละหน้าที่เนมสเปซต้องการ:
i18n.json
{
"pages" : {
"*" : [ "common" ] ,
"/" : [ "home" ] ,
"/cart" : [ "cart" ] ,
"/content/[slug]" : [ "content" ] ,
"rgx:^/account" : [ "account" ]
}
// rest of config here...
}อ่านที่นี่เกี่ยวกับวิธีเพิ่มไฟล์เนมสเปซ JSON
การแปลครั้งต่อไปทำให้มั่นใจได้ว่าแต่ละหน้ามีเฉพาะเนมสเปซด้วยภาษาปัจจุบัน ดังนั้นหากเรามี 100 สถานที่จะมีเพียง 1 ที่จะโหลด
ในการทำเช่นนี้เราใช้ webpack loader ที่โหลดไฟล์การแปลที่จำเป็นภายในวิธีการถัดไป. js ( getstaticprops , getServersideprops หรือ getInitialProps ) หากคุณมีหนึ่งในวิธีการเหล่านี้อยู่แล้วในหน้าของคุณ WebPack Loader จะใช้วิธีการของคุณเอง แต่ค่าเริ่มต้นที่จะใช้คือ:
getStaticProps นี่เป็น วิธีเริ่มต้นที่ใช้ในหน้าส่วนใหญ่ เว้นแต่จะเป็นหน้าเว็บที่ระบุไว้ในสองจุดถัดไป นี่คือประสิทธิภาพดังนั้นการคำนวณจะดำเนินการในเวลาสร้างแทนที่จะใช้เวลาร้องขอgetServerSideProps นี่เป็น วิธีเริ่มต้นสำหรับหน้าแบบไดนามิก เช่น [slug].js หรือ [...catchall].js นี่เป็นเพราะสำหรับหน้าเหล่านี้มีความจำเป็นที่จะต้องกำหนด getStaticPaths และไม่มีความรู้ว่ากระสุนควรเป็นอย่างไรสำหรับแต่ละสถานที่ ในทำนองเดียวกันมันเป็นอย่างไรโดยค่าเริ่มต้นเท่านั้นที่คุณเขียน getStaticPaths แล้วมันจะใช้ getStaticProps เพื่อโหลดการแปลgetInitialProps นี่เป็น วิธีเริ่มต้นสำหรับหน้าเหล่านี้ที่ใช้ hoc นี่คือเพื่อหลีกเลี่ยงความขัดแย้งเพราะ HOC สามารถเขียนทับ getInitialProps ได้ กระบวนการทั้งหมดนี้มีความโปร่งใส ดังนั้นในหน้าเว็บของคุณคุณสามารถใช้เบ็ด useTranslation โดยตรงเพื่อใช้เนมสเปซและคุณไม่จำเป็นต้องทำสิ่งอื่นใด
หากด้วยเหตุผลบางอย่างที่คุณใช้ getInitialProps ในไฟล์ _app.js ของคุณการแปลจะถูกโหลดลงใน getInitialProps ของคุณจาก _app.js เท่านั้น เราขอแนะนำให้เหตุผลในการเพิ่มประสิทธิภาพที่คุณไม่ได้ใช้วิธีนี้เว้นแต่จะจำเป็นอย่างยิ่ง
yarn add next-translate next-translate-plugin เป็นเครื่องมือที่ช่วยให้นักพัฒนาสามารถจัดการการแปลได้อย่างมีประสิทธิภาพในแต่ละหน้าในระหว่างกระบวนการสร้าง มันแตกต่างจากแพ็คเกจ next-translate ซึ่งช่วยให้นักพัฒนาสามารถเข้าถึงการแปลในรหัสที่จำเป็น ปลั๊กอินทำงานโดยแยกวิเคราะห์ทุกหน้าค้นหาการแปลและเขียนไฟล์หน้าใหม่เพิ่มการแปลลงไป สิ่งนี้ทำให้ปลั๊กอินเป็นโซลูชันที่มีประสิทธิภาพและยืดหยุ่นมากขึ้นสำหรับการจัดการการแปลภายในแอปพลิเคชัน Next.js ขอแนะนำให้ติดตั้งปลั๊กอินเป็น devdependency
yarn add next-translate-plugin -Dในไฟล์ next.config.js ของคุณ:
const nextTranslate = require ( 'next-translate-plugin' )
module . exports = nextTranslate ( ) หรือหากคุณมีไฟล์ next.config.js อยู่แล้วและต้องการเปลี่ยนแปลงการเปลี่ยนแปลงให้ส่งวัตถุ config ไปยัง nextTranslate() ตัวอย่างเช่น webpack คุณสามารถทำได้เช่นนี้:
const nextTranslate = require ( 'next-translate-plugin' )
module . exports = nextTranslate ( {
webpack : ( config , { isServer , webpack } ) => {
return config ;
}
} ) เพิ่มไฟล์การกำหนดค่า i18n.json (หรือ i18n.js ด้วย module.exports ) ในรูทของโครงการ แต่ละหน้าควรมีเนมสเปซ ลองดูในส่วนการกำหนดค่าสำหรับรายละเอียดเพิ่มเติม
{
"locales" : [ " en " , " ca " , " es " ],
"defaultLocale" : " en " ,
"pages" : {
"*" : [ " common " ],
"/" : [ " home " , " example " ],
"/about" : [ " about " ]
}
}ในไฟล์การกำหนดค่าคุณสามารถใช้ทั้งการกำหนดค่าที่เราระบุไว้ที่นี่และคุณสมบัติของตัวเองเกี่ยวกับความเป็นสากลของ Next.js 10
โดยค่าเริ่มต้นจะมีการระบุเนมสเปซในไดเรกทอรีรูท /loclees ด้วยวิธีนี้:
/สถานที่
.
├── ca
│ ├── common.json
│ └── home.json
├── en
│ ├── common.json
│ └── home.json
└── es
├── common.json
└── home.json ชื่อไฟล์แต่ละตัวตรงกับเนมสเปซที่ระบุไว้ในคุณสมบัติการกำหนดค่า pages ในขณะที่เนื้อหาแต่ละไฟล์ควรคล้ายกับนี้:
{
"title" : " Hello world " ,
"variable-example" : " Using a variable {{count}} "
}อย่างไรก็ตามคุณสามารถใช้ปลายทางอื่นเพื่อบันทึกไฟล์เนมสเปซของคุณโดยใช้คุณสมบัติการกำหนดค่า LoadLocaleFrom:
i18n.js
{
// ...rest of config
"loadLocaleFrom" : ( lang , ns ) =>
// You can use a dynamic import, fetch, whatever. You should
// return a Promise with the JSON file.
import ( `./myTranslationsFiles/ ${ lang } / ${ ns } .json` ) . then ( ( m ) => m . default ) ,
}จากนั้นใช้การแปลในหน้าและส่วนประกอบ:
หน้า/example.js
import useTranslation from 'next-translate/useTranslation'
export default function ExamplePage ( ) {
const { t , lang } = useTranslation ( 'common' )
const example = t ( 'variable-example' , { count : 42 } )
return < div > { example } </ div > // <div>Using a variable 42</div>
}คุณสามารถใช้การแปลโดยตรงบนหน้าเว็บของคุณคุณไม่ต้องกังวลเกี่ยวกับการโหลดไฟล์ namespaces ด้วยตนเองในแต่ละหน้า ปลั๊กอินการแปลถัดไปจะโหลดเฉพาะเนมสเปซที่หน้าต้องการและใช้ภาษาปัจจุบันเท่านั้น
ในไฟล์การกำหนดค่าคุณสามารถใช้ทั้งการกำหนดค่าที่เราระบุไว้ที่นี่และคุณสมบัติของตัวเองเกี่ยวกับความเป็นสากลของ Next.js 10
| ตัวเลือก | คำอธิบาย | พิมพ์ | ค่าเริ่มต้น |
|---|---|---|---|
defaultLocale | ISO ของสถานที่เริ่มต้น ("en" เป็นค่าเริ่มต้น) | string | "en" |
locales | อาร์เรย์ที่มีทุกภาษาที่จะใช้ในโครงการ | string[] | [] |
loadLocaleFrom | เปลี่ยนวิธีการโหลดเนมสเปซ | function ที่ส่งคืน Promise กับ JSON | โดยค่าเริ่มต้นคือการโหลดเนมสเปซจากไดเรกทอรีรากที่ ตั้ง |
pages | วัตถุที่กำหนดเนมสเปซที่ใช้ในแต่ละหน้า ตัวอย่างของวัตถุ: {"/": ["home", "example"]} ในการเพิ่มเนมสเปซในทุกหน้าคุณควรใช้คีย์ "*" , Ex: {"*": ["common"]} นอกจากนี้ยังเป็นไปได้ที่จะใช้ regex โดยใช้ rgx: ด้านหน้า: {"rgx:/form$": ["form"]} นอกจากนี้คุณยังสามารถใช้ฟังก์ชั่นแทนอาร์เรย์เพื่อให้เนมสเปซบางอย่างขึ้นอยู่กับกฎบางอย่างเช่น: { "/": ({ req, query }) => query.type === 'example' ? ['example'] : []} | Object<string[] or function> | {} |
logger | ฟังก์ชั่นเพื่อบันทึก คีย์ที่หายไป ในการพัฒนาและการผลิต หากคุณใช้ i18n.json เป็นไฟล์กำหนดค่าคุณควรเปลี่ยนเป็น i18n.js | function | โดยค่าเริ่มต้น Logger เป็นฟังก์ชั่นที่ทำ console.warn เฉพาะในการพัฒนา |
loggerEnvironment | สตริงเพื่อกำหนดว่าตัวบันทึกควรทำงานในเบราว์เซอร์ในโหนดหรือทั้งสองอย่าง | "node" | "browser" | "both" | "browser" |
logBuild | แต่ละหน้ามีบันทึกที่ระบุ: เนมสเปซ, ภาษาปัจจุบันและวิธีการที่ใช้ในการโหลดเนมสเปซ ด้วยสิ่งนี้คุณสามารถปิดการใช้งานได้ | Boolean | true |
loader | หากคุณต้องการปิดใช้งาน WebPack Loader และโหลดเนมสเปซด้วยตนเองในแต่ละหน้าเราให้โอกาสคุณในการทำเช่นนั้นโดยปิดการใช้งานตัวเลือกนี้ | Boolean | true |
interpolation | เปลี่ยนตัวคั่นที่ใช้สำหรับการแก้ไข | {prefix: string; suffix: string, formatter: function } | {prefix: '{{', suffix: '}}'} |
keySeparator | เปลี่ยนตัวคั่นที่ใช้สำหรับคีย์ซ้อนกัน ตั้งค่าเป็น false เพื่อปิดการใช้งานการทำรังในไฟล์การแปล JSON จะมีประโยชน์หากคุณต้องการใช้ข้อความธรรมชาติเป็นกุญแจ | string | false | '.' |
nsSeparator | ถ่านเพื่อแยกเนมสเปซจากคีย์ คุณควรตั้งค่าเป็น false หากคุณต้องการใช้ข้อความธรรมชาติเป็นกุญแจ | string | false | ':' |
defaultNS | เนมสเปซเริ่มต้นใช้ถ้าไม่ผ่านไปยัง useTranslation หรือในคีย์การแปล | string | undefined |
staticsHoc | hocs ที่เรามีใน API ของเรา (appwithi18n) อย่าใช้ hoist-non-reactic-statics เพื่อไม่ให้รวม KB มากกว่าที่จำเป็น (ค่าคงที่แตกต่างจาก getInitialProps ในหน้าไม่ค่อยใช้) หากคุณมีความขัดแย้งกับสถิติใด ๆ คุณสามารถเพิ่มรูปแบบที่ไม่ได้เกิดขึ้น (หรือทางเลือกอื่น ๆ ) ที่นี่ ดูตัวอย่าง | Function | null |
extensionsRgx | เปลี่ยน regex ที่ใช้โดย webpack loader เพื่อค้นหาหน้า next.js | Regex | /.(tsx|ts|js|mjs|jsx)$/ |
revalidate | หากคุณต้องการให้มีการตรวจสอบใหม่เริ่มต้นในแต่ละหน้าเราจะให้โอกาสคุณทำโดยผ่านหมายเลขเพื่อทำการตรวจสอบใหม่ คุณยังสามารถกำหนด getStaticProps บนหน้าเว็บที่มีจำนวน revalidate ที่แตกต่างกันและแทนที่การแทนที่ค่าเริ่มต้นนี้ | Number | หากคุณไม่ได้กำหนดโดยค่าเริ่มต้นหน้าจะไม่มีการทบทวนอีกครั้ง |
pagesInDir | หากคุณรัน next ./my-app เพื่อเปลี่ยนหน้าเว็บของคุณคุณสามารถกำหนด my-app/pages ได้ที่นี่เพื่อให้การแปลครั้งต่อไปสามารถเดาได้ว่าพวกเขาอยู่ที่ไหน | String | หากคุณไม่ได้กำหนดโดยค่าเริ่มต้นหน้าจะถูกค้นหาในสถานที่คลาสสิกเช่น pages และ src/pages |
localesToIgnore | ระบุสถานที่เหล่านี้ให้เพิกเฉยเมื่อคุณนำหน้าสถานที่เริ่มต้นโดยใช้มิดเดิลแวร์ (ใน +12 ถัดไปเรียนรู้วิธีการทำ) | Array<string> | ['default'] |
allowEmptyStrings | เปลี่ยนวิธีการจัดการสตริงว่างเปล่าที่แปล หากละเว้นหรือส่งผ่านเป็นจริงมันจะส่งคืนสตริงเปล่า หากผ่านเป็นเท็จให้ส่งคืนชื่อคีย์เอง (รวมถึง NS) | Boolean | true |
ขนาด : ~ 150b?
ตะขอนี้เป็นวิธีที่แนะนำในการใช้การแปลในหน้า / ส่วนประกอบของคุณ
ตัวอย่าง:
import React from 'react'
import useTranslation from 'next-translate/useTranslation'
export default function Description ( ) {
const { t , lang } = useTranslation ( 'ns1' ) // default namespace (optional)
const title = t ( 'title' )
const titleFromOtherNamespace = t ( 'ns2:title' )
const description = t `description` // also works as template string
const example = t ( 'ns2:example' , { count : 3 } ) // and with query params
const exampleDefault = t ( 'ns:example' , { count : 3 } , { default : "The count is: {{count}}." } ) // and with default translation
return (
< >
< h1 > { title } </ h1 >
< p > { description } </ p >
< p > { example } </ p >
< >
)
} ฟังก์ชัน t :
i18nKey คล้ายกับ useTranslation แต่ไม่มีเบ็ด ผู้ช่วยนี้ใช้งานได้ใน แอพ DIR เท่านั้น
const { t , lang } = createTranslation ( 'ns1' ) // default namespace (optional)
const title = t ( 'title' )ขนาด : ~ 560b?
มันเป็นอีกทางเลือกหนึ่งในการใช้ hook useTranslation แต่ในช่วงเฉพาะสำหรับส่วนประกอบเหล่านี้ที่ไม่สามารถใช้งานได้ (ไม่แนะนำให้ใช้ hook useTranslation ) ดีกว่า)
The withTranslation HOC ส่งคืนส่วนประกอบด้วยเสาพิเศษชื่อ i18n (วัตถุ {t: ฟังก์ชั่น, lang: string})
ตัวอย่าง:
import React from 'react'
import withTranslation from 'next-translate/withTranslation'
class Description extends React . Component {
render ( ) {
const { t , lang } = this . props . i18n
const description = t ( 'common:description' )
return < p > { description } </ p >
}
}
export default withTranslation ( NoFunctionalComponent ) คล้ายกับ useTranslation("common") คุณสามารถโทร withTranslation ด้วยพารามิเตอร์ที่สองที่กำหนด namespace เริ่มต้นที่จะใช้:
export default withTranslation(NoFunctionalComponent, "common")
ขนาด : ~ 1.4kb?
บางครั้งเราจำเป็นต้องทำการแปลด้วย HTML ภายในข้อความ (ตัวหนาลิงก์ ฯลฯ ) ส่วนประกอบ Trans เป็นสิ่งที่คุณต้องการสำหรับสิ่งนี้ เราแนะนำให้ใช้ส่วนประกอบนี้เฉพาะในกรณีนี้สำหรับกรณีอื่น ๆ เราขอแนะนำให้ใช้ hook useTranslation แทน
ตัวอย่าง:
// The defined dictionary entry is like:
// "example": "<0>The number is <1>{{count}}</1></0>",
< Trans
i18nKey = "common:example"
components = { [ < Component /> , < b className = "red" /> ] }
values = { { count : 42 } }
/> หรือใช้ components prop เป็นวัตถุ:
// The defined dictionary entry is like:
// "example": "<component>The number is <b>{{count}}</b></component>",
< Trans
i18nKey = "common:example"
components = { {
component : < Component /> ,
b : < b className = "red" /> ,
} }
values = { { count : 42 } }
defaultTrans = "<component>The number is <b>{{count}}</b></component>"
/>i18nKey - สตริง - คีย์ของรายการ I18N (เนมสเปซ: คีย์)components - อาร์เรย์ | วัตถุ - ในกรณีของอาร์เรย์แต่ละดัชนีสอดคล้องกับแท็กที่กำหนด <0> / <1> ในกรณีของวัตถุแต่ละคีย์สอดคล้องกับแท็กที่กำหนด <example>values - Object - Query Paramsfallback - String | สตริง [] - ไม่บังคับ ทางเลือก i18nkey ถ้า i18nkey ไม่ตรงกันdefaultTrans - String - การแปลเริ่มต้นสำหรับคีย์ หากมีการใช้คีย์ทางเลือกมันจะถูกใช้หลังจากหมดไปทั้งหมดns - Namespace ที่จะใช้เมื่อไม่มีการฝังใน i18nKeyreturnObjects - Boolean - รับส่วนหนึ่งของ JSON พร้อมคำแปลทั้งหมด ดูเพิ่มเติม ในกรณีที่เราต้องการฟังก์ชั่นขององค์ประกอบ Trans แต่จำเป็นต้องมี สตริง ที่จะทำการแก้ไขมากกว่าเอาต์พุตของฟังก์ชัน t(props.i18nKey) นอกจากนี้ยังมีองค์ประกอบ TransText ซึ่งใช้เสา text แทน i18nKey
text - สตริง - สตริงที่ (ทางเลือก) มีแท็กที่ต้องการการแก้ไขcomponents - อาร์เรย์ | Object - สิ่งนี้มีพฤติกรรมเหมือนกับ Trans (ดูด้านบน) สิ่งนี้มีประโยชน์อย่างยิ่งเมื่อทำการแมปผ่านเอาต์พุตของ t() ด้วย returnObjects: true :
// The defined dictionary entry is like:
// "content-list": ["List of <link>things</link>", "with <em>tags</em>"]
const contentList = t ( 'someNamespace:content-list' , { } , { returnObjects : true } ) ;
{ contentList . map ( ( listItem : string ) => (
< TransText
text = { listItem }
components = { {
link : < a href = "some-url" /> ,
em : < em /> ,
} }
/>
) }ขนาด : ~ 1.5kb?
ส่วนประกอบ DynamicNamespaces มีประโยชน์ในการโหลดเนมสเปซแบบไดนามิกตัวอย่างเช่นในโมดอล
ตัวอย่าง:
import React from 'react'
import Trans from 'next-translate/Trans'
import DynamicNamespaces from 'next-translate/DynamicNamespaces'
export default function ExampleWithDynamicNamespace ( ) {
return (
< DynamicNamespaces namespaces = { [ 'dynamic' ] } fallback = "Loading..." >
{ /* ALSO IS POSSIBLE TO USE NAMESPACES FROM THE PAGE */ }
< h1 >
< Trans i18nKey = "common:title" />
</ h1 >
{ /* USING DYNAMIC NAMESPACE */ }
< Trans i18nKey = "dynamic:example-of-dynamic-translation" />
</ DynamicNamespaces >
)
} โปรดจำไว้ว่า ['dynamic'] namespace ไม่ ควรแสดงรายการในการกำหนดค่า pages :
pages: {
'/my-page' : [ 'common' ] , // only common namespace
}namespaces - สตริง [] - รายการของเนมสเปซแบบไดนามิกที่จะดาวน์โหลด - จำเป็นfallback - ReactNode - ทางเลือกที่จะแสดงในขณะที่เนมสเปซกำลังโหลด - ไม่จำเป็น .dynamic - ฟังก์ชั่น - โดยค่าเริ่มต้นจะใช้ LoadLocaleFrom ในการกำหนดค่าเพื่อโหลดเนมสเปซ แต่คุณสามารถระบุปลายทางอื่นได้ - ไม่จำเป็น .ขนาด : ~ 1.3kb?
ฟังก์ชั่นแบบอะซิงโครนัสเพื่อโหลดฟังก์ชัน t นอกส่วนประกอบ / หน้า มันทำงานได้ทั้งฝั่งเซิร์ฟเวอร์และฝั่งไคลเอ็นต์
เราสามารถใช้เนมสเปซใด ๆ ที่นี่ไม่จำเป็นต้องเป็นเนมสเปซที่กำหนดไว้ในการกำหนดค่า "หน้า" มันดาวน์โหลดเนมสเปซที่ระบุเป็นพารามิเตอร์บนรันไทม์
คุณสามารถโหลดเนมสเปซหลายตัวโดยให้อาร์เรย์เป็นพารามิเตอร์ในกรณีนี้เนมสเปซเริ่มต้นจะเป็นกำปั้น
ตัวอย่างภายใน getStaticProps :
import getT from 'next-translate/getT'
// ...
export async function getStaticProps ( { locale } ) {
const t = await getT ( locale , 'common' )
const title = t ( 'title' )
return { props : { title } }
}ตัวอย่างภายในเส้นทาง API:
import getT from 'next-translate/getT'
export default async function handler ( req , res ) {
const t = await getT ( req . query . __nextLocale , 'common' )
const title = t ( 'title' )
res . statusCode = 200
res . setHeader ( 'Content-Type' , 'application/json' )
res . end ( JSON . stringify ( { title } ) )
}ตัวอย่างการโหลดเนมสเปซหลายตัว:
import getT from 'next-translate/getT'
export default async function handler ( req , res ) {
const t = await getT ( req . query . __nextLocale , [ 'common' , 'errors' ] )
const title = t ( 'title' ) // The default namespace is the first one.
const errorMessage = t ( 'errors:app_error' ) // The default namespace is the first one.
res . statusCode = 200
res . setHeader ( 'Content-Type' , 'application/json' )
res . end ( JSON . stringify ( { title } ) )
}ขนาด : ~ 3KB?
I18nProvider เป็นผู้ให้บริการบริบทที่ใช้งานภายในโดย Translate ภายในเพื่อให้ Lang ปัจจุบันและ Namespaces หน้า ดังนั้นบางทีคุณอาจไม่ต้องการสิ่งนี้
อย่างไรก็ตามมันสัมผัสกับ API เพราะอาจมีประโยชน์ในบางกรณี ตัวอย่างเช่นการใช้การแปลหลายภาษาในหน้า
I18nProvider กำลังสะสมเนมสเปซดังนั้นคุณสามารถเปลี่ยนชื่อตัวใหม่เพื่อรักษาตัวเก่า
import React from 'react'
import I18nProvider from 'next-translate/I18nProvider'
import useTranslation from 'next-translate/useTranslation'
// Import English common.json
import commonEN from '../../locales/en/common.json'
function PageContent ( ) {
const { t , lang } = useTranslation ( )
console . log ( lang ) // -> current language
return (
< div >
< p > { t ( 'common:example' ) /* Current language */ } </ p >
< p > { t ( 'commonEN:example' ) /* Force English */ } </ p >
</ div >
)
}
export default function Page ( ) {
const { lang } = useTranslation ( )
return (
< I18nProvider lang = { lang } namespaces = { { commonEN } } >
< PageContent />
</ I18nProvider >
)
}ขนาด : ~ 3.7kb?
appWithI18n ใช้งานภายในโดย Translate ดังนั้นบางทีคุณอาจไม่ต้องการสิ่งนี้ อย่างไรก็ตามเราเปิดเผยใน API ในกรณีที่คุณปิดใช้งานตัวเลือก Webpack Loader และตัดสินใจโหลดเนมสเปซด้วยตนเอง
หากคุณไม่ต้องการใช้ WebPack Loader คุณควรใส่สิ่งนี้ไว้ในไฟล์ _app.js ของคุณ (และสร้างไฟล์ _app.js หากคุณไม่มี)
ตัวอย่าง:
_app.js
import appWithI18n from 'next-translate/appWithI18n'
import i18nConfig from '../i18n'
function MyApp ( { Component , pageProps } ) {
return < Component { ... pageProps } />
}
// Wrapping your _app.js
export default appWithI18n ( MyApp , {
... i18nConfig ,
// Set to false if you want to load all the namespaces on _app.js getInitialProps
skipInitialProps : true ,
} ) หาก skipInitialProps=true คุณควรใช้ตัวช่วยโหลด Loadnamespaces เพื่อโหลดเนมสเปซด้วยตนเองในแต่ละหน้า
ขนาด : ~ 1.9kb?
loadNamespaces ถูกใช้ภายในโดยการแปลครั้งต่อไป ดังนั้นบางทีคุณอาจไม่ต้องการสิ่งนี้ อย่างไรก็ตามเราเปิดเผยใน API ในกรณีที่คุณปิดใช้งานตัวเลือก Webpack Loader และตัดสินใจโหลดเนมสเปซด้วยตนเอง
ในการโหลดเนมสเปซคุณจะต้องส่งคืนอุปกรณ์ประกอบฉากที่ผู้ช่วยให้กลับมา
import loadNamespaces from 'next-translate/loadNamespaces'
export function getStaticProps ( { locale } ) {
return {
props : {
... ( await loadNamespaces ( { locale , pathname : '/about' } ) ) ,
}
}
} ในการทำงานได้ดีมีความจำเป็นที่ _app.js ของคุณจะถูกห่อหุ้มด้วย appwithi18n นอกจากนี้คุณสมบัติการกำหนดค่า loadLocaleFrom ยังเป็น ข้อบังคับ ในการกำหนด
เราสนับสนุน 6 รูปแบบพหูพจน์ (นำมาจากหน้า cldr plurals) โดยการเพิ่มคีย์คำต่อท้ายนี้ (หรือทำรังภายใต้คีย์โดยไม่มีคำนำหน้า _ ):
_zero_one (เอกพจน์)_two (คู่)_few (paucal)_many (ใช้เป็นเศษส่วนหากมีคลาสแยกต่างหาก)_other (จำเป็น - รูปแบบพหูพจน์ทั่วไป - ใช้ถ้าภาษามีเพียงรูปแบบเดียว)ดูข้อมูลเพิ่มเติมเกี่ยวกับ Plurals ที่นี่
มีเพียงคนสุดท้ายเท่านั้น _other เป็นสิ่งจำเป็นเพราะเป็นรูปแบบพหูพจน์ทั่วไปเพียงอย่างเดียวที่ใช้ในทุกสถานที่
รูปแบบพหูพจน์อื่น ๆ ทั้งหมดขึ้นอยู่กับสถานที่ ตัวอย่างเช่นภาษาอังกฤษมีเพียงสอง: _one และ _other (1 แมวกับแมว 2 ตัว) บางภาษามีมากขึ้นเช่นรัสเซียและอาหรับ
นอกจากนี้เรายังรองรับ การจับคู่ที่แน่นอน โดยระบุหมายเลข ( _0 , _999 ) และสิ่งนี้ใช้ได้กับทุกที่ นี่คือตัวอย่าง:
รหัส:
// **Note**: Only works if the name of the variable is {{count}}.
t ( 'cart-message' , { count } )เนมสเปซ:
{
"cart-message_0" : "The cart is empty" , // when count === 0
"cart-message_one" : "The cart has only {{count}} product" , // singular
"cart-message_other" : "The cart has {{count}} products" , // plural
"cart-message_999" : "The cart is full" , // when count === 999
}หรือ
{
"cart-message" : {
"0" : "The cart is empty" , // when count === 0
"one" : "The cart has only {{count}} product" , // singular
"other" : "The cart has {{count}} products" , // plural
"999" : "The cart is full" , // when count === 999
}
}Intl.Pliuralrules API ใช้ได้เฉพาะกับเบราว์เซอร์ที่ทันสมัย หากคุณต้องการใช้ในเบราว์เซอร์ดั้งเดิมคุณควรเพิ่มโพลีฟิล
คุณสามารถกำหนด HTML ภายในการแปลด้วยวิธีนี้:
{
"example-with-html" : " <0>This is an example <1>using HTML</1> inside the translation</0> "
}ตัวอย่าง:
import Trans from 'next-translate/Trans'
// ...
const Component = ( props ) => < p { ... props } />
// ...
< Trans
i18nKey = "namespace:example-with-html"
components = { [ < Component /> , < b className = "red" /> ] }
/ >ผลการแสดงผล:
< p > This is an example < b class =" red " > using HTML </ b > inside the translation </ p > แต่ละดัชนีของอาร์เรย์ components นั้นสอดคล้องกับ <index></index> ของคำจำกัดความ
ในอาร์เรย์ components ไม่จำเป็นต้องผ่านลูกของแต่ละองค์ประกอบ เด็กจะถูกคำนวณ
ในเนมสเปซมีความเป็นไปได้ที่จะกำหนดกุญแจซ้อนเช่นนี้:
{
"nested-example" : {
"very-nested" : {
"nested" : " Nested example! "
}
}
}ในการใช้งานคุณควรใช้ "." เป็นตัวแยก ID:
t `namespace:nested-example.very-nested.nested`ยังเป็นไปได้ที่จะใช้เป็นอาร์เรย์:
{
"array-example" : [
{ "example" : " Example {{count}} " },
{ "another-example" : " Another example {{count}} " }
]
} และรับการแปลอาร์เรย์ทั้งหมดด้วยตัวเลือก returnObjects :
t ( 'namespace:array-example' , { count : 1 } , { returnObjects : true } )
/*
[
{ "example": "Example 1" },
{ "another-example": "Another example 1" }
]
*/ นอกจากนี้ยังเป็นไปได้ที่จะได้รับการแปลทั้งหมดโดยใช้ keyseparator เป็นคีย์ค่าเริ่มต้นคือ '.' -
t ( 'namespace:.' , { count : 1 } , { returnObjects : true } )
/*
{
"array-example": [
{ "example": "Example 1" },
{ "another-example": "Another example 1" }
]
}
*/ หากไม่มีการแปลคุณสามารถกำหนดค่าโทร ( string|string[] ) เพื่อค้นหาการแปลอื่น ๆ :
const { t } = useTranslation ( )
const textOrFallback = t (
'ns:text' ,
{ count : 1 } ,
{
fallback : 'ns:fallback' ,
}
)รายชื่อทางเลือก:
const { t } = useTranslation ( )
const textOrFallback = t (
'ns:text' ,
{ count : 42 } ,
{
fallback : [ 'ns:fallback1' , 'ns:fallback2' ] ,
}
)ในองค์ประกอบทรานส์:
< Trans
i18nKey = "ns:example"
components = { [ < Component /> , < b className = "red" /> ] }
values = { { count : 42 } }
fallback = { [ 'ns:fallback1' , 'ns:fallback2' ] } // or string with just 1 fallback
/> คุณสามารถจัดรูปแบบพารามิเตอร์โดยใช้ฟัง interpolation.format นการแก้ไขการกำหนดค่าฟอร์แมต
ใน i18n.js :
const formatters = {
es : new Intl . NumberFormat ( "es-ES" ) ,
en : new Intl . NumberFormat ( "en-EN" ) ,
}
return {
// ...
interpolation : {
format : ( value , format , lang ) => {
if ( format === 'number' ) return formatters [ lang ] . format ( value )
return value
}
}
}ในเนมสเปซภาษาอังกฤษ:
{
"example" : " The number is {{count, number}} "
}ในเนมสเปซสเปน:
{
"example" : " El número es {{count, number}} "
}โดยใช้:
t ( 'example' , { count : 33.5 } )ผลตอบแทน:
The number is 33.5El número es 33,5 ในการเปลี่ยนภาษาปัจจุบันคุณสามารถใช้ Next.js Navigation (ลิงก์และเราเตอร์) ที่ผ่านเสา locale ส
ตัวอย่างขององค์ประกอบ ChangeLanguage ที่เป็นไปได้โดยใช้ hook useRouter จาก Next.js :
import React from 'react'
import Link from 'next/link'
import useTranslation from 'next-translate/useTranslation'
import i18nConfig from '../i18n.json'
const { locales } = i18nConfig
export default function ChangeLanguage ( ) {
const { t , lang } = useTranslation ( )
return locales . map ( ( lng ) => {
if ( lng === lang ) return null
return (
< Link href = "/" locale = { lng } key = { lng } >
{ t ( `layout:language-name- ${ lng } ` ) }
</ Link >
)
} )
} คุณสามารถใช้ setLanguage เพื่อเปลี่ยนภาษาในขณะที่รักษาหน้าเดียวกัน
import React from 'react'
import setLanguage from 'next-translate/setLanguage'
export default function ChangeLanguage ( ) {
return (
< button onClick = { async ( ) => await setLanguage ( 'en' ) } > EN </ button >
)
} อีกวิธีหนึ่งในการเข้าถึงรายการ locales เพื่อเปลี่ยนภาษาคือการใช้ Next.js router รายการ locales สามารถเข้าถึงได้โดยใช้ hook userouter next.js
คุณสามารถตั้งค่าคุกกี้ชื่อ NEXT_LOCALE ด้วยภาษาที่ผู้ใช้กำหนดเป็นค่าวิธีนี้สามารถบังคับสถานที่ได้
ตัวอย่างของ hook:
import { useRouter } from 'next/router'
// ...
function usePersistLocaleCookie ( ) {
const { locale , defaultLocale } = useRouter ( )
useEffect ( persistLocaleCookie , [ locale , defaultLocale ] )
function persistLocaleCookie ( ) {
if ( locale !== defaultLocale ) {
const date = new Date ( )
const expireMs = 100 * 24 * 60 * 60 * 1000 // 100 days
date . setTime ( date . getTime ( ) + expireMs )
document . cookie = `NEXT_LOCALE= ${ locale } ;expires= ${ date . toUTCString ( ) } ;path=/`
}
}
} ในบางกรณีเมื่อหน้าอยู่ในภาษาปัจจุบันคุณอาจต้องการทำข้อยกเว้นบางอย่างที่แสดงข้อความในภาษาอื่น
ในกรณีนี้คุณสามารถทำได้โดยใช้ I18nProvider
เรียนรู้วิธีการทำที่นี่
การแปลครั้งต่อไปใช้โดยค่าเริ่มต้นไดเรกทอรีการทำงานปัจจุบันของกระบวนการ node.js ( process.cwd() )
หากคุณต้องการเปลี่ยนคุณสามารถใช้:
NEXT_TRANSLATE_PATH รองรับทั้งเส้นทางที่สัมพันธ์กันและสัมบูรณ์process.chdir(PATH_TO_NEXT_TRANSLATE) เพื่อย้าย process.cwd() เมื่อพูดถึงส่วนประกอบเซิร์ฟเวอร์และส่วนประกอบไคลเอนต์อาจเป็นเรื่องท้าทายที่จะโหลดสิ่งเดียวกันในหน้าต่างๆ เพื่อให้กระบวนการนี้ง่ายขึ้นเราได้ แยกความซับซ้อนทั้งหมด โดยใช้ next-translate-plugin
หากคุณสนใจที่จะเรียนรู้เพิ่มเติมเกี่ยวกับวิธีการแปลครั้งต่อไปกับการทำงานใหม่ของ Next.js 13 Paradigm Dir Dir ให้ตรวจสอบ บทความนี้ เพื่อหาคำอธิบายโดยละเอียด
หากคุณใช้โฟลเดอร์ "แอป" แทนโฟลเดอร์ "หน้า" next-translate-plugin จะตรวจจับการเปลี่ยนแปลงโดยอัตโนมัติและคุณไม่จำเป็นต้องสัมผัสการกำหนดค่าการแปลครั้งต่อไปใด ๆ ความแตกต่างเพียงอย่างเดียวคือคุณสมบัติการกำหนดค่า "หน้า" จะอ้างอิงหน้าเว็บที่อยู่ภายในโฟลเดอร์ "แอป"
i18n.js
module . exports = {
locales : [ 'en' , 'ca' , 'es' ] ,
defaultLocale : 'en' ,
pages : {
'*' : [ 'common' ] ,
'/' : [ 'home' ] , // app/page.tsx
'/second-page' : [ 'home' ] , // app/second-page/page.tsx
} ,
} เพียงแค่เปลี่ยนโฟลเดอร์ "หน้า" เป็น "แอพ" คุณสามารถใช้การแปลภายในหน้าเว็บของคุณโดยใช้ hook useTranslation หรือส่วนประกอบ Trans คุณจะยังคงเห็นบันทึก (ถ้าเปิดใช้งาน) เพื่อทราบว่าเนมสเปซใดที่โหลดในแต่ละหน้าและทุกอย่างอื่นควรจะเหมือนกัน
- หน้าเซิร์ฟเวอร์/ส่วนประกอบ (+0KB): app/page.js :
import useTranslation from 'next-translate/useTranslation'
export default function HomePage ( ) {
const { t , lang } = useTranslation ( 'home' )
return < h1 > { t ( 'title' ) } </ h1 >
} ? ️หน้าไคลเอนต์/ส่วนประกอบ (+498b): app/checkout/page.js
"use client"
import useTranslation from 'next-translate/useTranslation'
export default function CheckoutPage ( ) {
const { t , lang } = useTranslation ( 'checkout' )
return < h1 > { t ( 'title' ) } </ h1 >
} Next.js 10 แนะนำการสนับสนุนการกำหนดเส้นทาง I18N ช่วยให้หน้าสามารถแสดงผลได้โดยการนำทางไปยัง /es/page-name โดยที่ pages/page-name.js เข้าถึงได้โดยใช้ hook useRouter เพื่อรับ locale
อย่างไรก็ตามเนื่องจากหน้าเว็บได้ถูกย้ายจาก pages เว็บไปยัง แอป DIR การกำหนดเส้นทาง i18n นี้ ไม่ทำงานอย่างถูกต้องอีกต่อไป
ในการแปลครั้งต่อไปเราได้เลือกที่จะนำฟังก์ชั่นนี้อีกครั้งเนื่องจากเรามุ่งมั่นที่จะเป็นห้องสมุดสำหรับการแปลหน้าเว็บแทนที่จะกำหนดเส้นทาง เราหวังว่าในอนาคตคุณลักษณะนี้จะถูกนำไปใช้ในไดเรกทอรี app
เราขอแนะนำสิ่งต่อไปนี้:
[lang] ในระดับแรก นั่นคือหน้าทั้งหมดของคุณจะอยู่ภายใน /app/[lang]i18n.(js|json) ไฟล์เพื่อให้มี /[lang] ที่จุดเริ่มต้น module.exports = {
locales: ['en', 'ca', 'es'],
defaultLocale: 'en',
pages: {
'*': ['common'],
- '/': ['home'],
+ '/[lang]': ['home'],
- '/second-page': ['home'],
+ '/[lang]/second-page': ['home'],
},
} ในระดับการแปลถัดไปเรา จะตรวจจับภาษาโดยอัตโนมัติ ตาม searchParams.get('lang') และ params.lang ดังนั้นคุณ ไม่จำเป็นต้องกำหนดค่าสำหรับแต่ละหน้า คุณสามารถใช้ next-translate ตาม ปกติ ภายในหน้าเซิร์ฟเวอร์/ไคลเอนต์/ส่วนประกอบ:
import useTranslation from 'next-translate/useTranslation'
import Trans from 'next-translate/Trans'
export default function Page ( ) {
const { t , lang } = useTranslation ( 'common' )
return (
< >
< h1 > { t `title` } </ h1 >
< Trans i18nKey = "common:another-text" components = { [ < b /> ] } />
</ >
)
} มีการสาธิต next-translate ใน next.js repo:
เพื่อใช้:
npx create-next-app --example with-next-translate with-next-translate-app
# or
yarn create next-app --example with-next-translate with-next-translate-appการสาธิตนี้อยู่ในที่เก็บนี้:
git clone [email protected]:aralroca/next-translate.gitcd next-translateyarn && yarn example:basicคล้ายกับการสาธิตพื้นฐาน แต่มีความพิเศษบางอย่าง: typescript, webpack 5, mdx, กับ _app.js ด้านบน, หน้าเว็บที่ตั้งอยู่บนโฟลเดอร์ SRC/Pages, โหลดสถานที่จาก SRC/การแปลที่มีโครงสร้างที่แตกต่างกัน
การสาธิตนี้อยู่ในที่เก็บนี้:
git clone [email protected]:aralroca/next-translate.gitcd next-translateyarn && yarn example:complex คล้ายกับการสาธิตที่ซับซ้อน แต่มีบางอย่างเพิ่มเติม: แทนที่จะเป็นโฟลเดอร์ pages เราใช้โฟลเดอร์แอพพลิเคชั่นถัดไป. js +13 กับระบบเลย์เอาต์ใหม่
การสาธิตนี้อยู่ในที่เก็บนี้:
git clone [email protected]:aralroca/next-translate.gitcd next-translateyarn && yarn example:with-app-directoryคล้ายกับตัวอย่างพื้นฐาน แต่การโหลดหน้าเนมสเปซหน้าปิดใช้งานตัวโหลดเว็บแพ็คด้วยตนเองในไฟล์ config i18n.json
เราไม่แนะนำให้ใช้ด้วยวิธีนี้ อย่างไรก็ตามเราให้โอกาสแก่ทุกคนที่จะทำเช่นนั้นหากพวกเขาไม่พอใจกับ webpack loader ของเรา
การสาธิตนี้อยู่ในที่เก็บนี้:
git clone [email protected]:aralroca/next-translate.gitcd next-translateyarn && yarn example:without-loader ขอบคุณไปที่คนที่ยอดเยี่ยมเหล่านี้ (คีย์อีโมจิ):
Aral Roca Gomez - | Vincent Ducorps | Björnคลั่ง | จัสติน | โพล - | Ademílson F. Tonato | ฟาเรนไฮต์ |
Bickmaev5 | ปิแอร์กริมดอด | โรมันมินชิน | ผู้มีเพศสัมพันธ์ | คาร์เรน | Giovanni Giordano | ยูจีน |
Andrew Chung | Thanh Minh | crouton | แพทริค | คนแวนทรอย | โจอี้ | Gurkerl83 |
Teemu Perämäki | Luis Serrano | j-schumann | Andre Hsu | Slevy85 | Bernd Artmüller | rihards Ščeredins |
N4N5 | Rubén Moya | Tom Esterez | Dan Needham | Bruno Antunes | Kaan Atakan | โรย |
Arnau Jiménez | Edwin Veldhuizen | DUC NGO VIET | Billel Helali | wuif | Michał Bar | wuif |
กลายเป็น MARCES Engel | Michał Bar | ทำให้เกิด | กลายเป็น MARCES Engel | Vasco Silva | Vsevolod Volkov | เฟลิกซ์หยาน |
มูฮัมหมัดอัล Ziqri | Marcelo Oliveira | Zack Sunderland | Andrew Ovens | Dani | Mateusz Lesiak | curetix |
honza - | Hardikbandhiya | Tim O. Peters | หลี่หมิง | Fernando GarcíaHernández | Hichem Fantar | Huseyin onal |
เจสซี่มาร์ติน |
โครงการนี้เป็นไปตามข้อกำหนดทั้งหมดของผู้เข้าร่วม การมีส่วนร่วมทุกชนิดยินดีต้อนรับ!