"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["49093"],{45776:function(e,n,s){s.r(n),s.d(n,{metadata:()=>t,contentTitle:()=>c,default:()=>p,assets:()=>d,toc:()=>h,frontMatter:()=>o});var t=JSON.parse('{"id":"i18n/tutorial","title":"i18n - Tutorial","description":"This tutorial will walk you through the basics of the Docusaurus i18n system.","source":"@site/docs/i18n/i18n-tutorial.mdx","sourceDirName":"i18n","slug":"/i18n/tutorial","permalink":"/docs/i18n/tutorial","draft":false,"unlisted":false,"editUrl":"https://github.com/facebook/docusaurus/edit/main/website/docs/i18n/i18n-tutorial.mdx","tags":[],"version":"current","lastUpdatedBy":"S\xe9bastien Lorber","lastUpdatedAt":1729847735000,"frontMatter":{"id":"tutorial","description":"This tutorial will walk you through the basics of the Docusaurus i18n system.","slug":"/i18n/tutorial"},"sidebar":"docs","previous":{"title":"i18n - Introduction","permalink":"/docs/i18n/introduction"},"next":{"title":"Using Git","permalink":"/docs/i18n/git"}}'),l=s("24246"),a=s("80980"),r=s("15398"),i=s("58636");let o={id:"tutorial",description:"This tutorial will walk you through the basics of the Docusaurus i18n system.",slug:"/i18n/tutorial"},c="i18n - Tutorial",d={},h=[{value:"Configure your site",id:"configure-your-site",level:2},{value:"Site configuration",id:"site-configuration",level:3},{value:"Theme configuration",id:"theme-configuration",level:3},{value:"Start your site",id:"start-your-site",level:3},{value:"Translate your site",id:"translate-your-site",level:2},{value:"Translate your React code",id:"translate-your-react-code",level:3},{value:"Pluralization",id:"pluralization",level:4},{value:"Translate plugin data",id:"translate-plugin-data",level:3},{value:"Translate Markdown files",id:"translate-markdown-files",level:3},{value:"Translate the docs",id:"translate-the-docs",level:4},{value:"Translate the blog",id:"translate-the-blog",level:4},{value:"Translate the pages",id:"translate-the-pages",level:4},{value:"Deploy your site",id:"deploy-your-site",level:2},{value:"Single-domain deployment",id:"single-domain-deployment",level:3},{value:"Multi-domain deployment",id:"multi-domain-deployment",level:3},{value:"Hybrid",id:"hybrid",level:3},{value:"Managing translations",id:"managing-translations",level:2}];function u(e){let n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.a)(),...e.components};return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(n.header,{children:(0,l.jsx)(n.h1,{id:"i18n---tutorial",children:"i18n - Tutorial"})}),"\n","\n",(0,l.jsxs)(n.p,{children:["This tutorial will walk you through the basics of the ",(0,l.jsx)(n.strong,{children:"Docusaurus i18n system"}),"."]}),"\n",(0,l.jsxs)(n.p,{children:["We will add ",(0,l.jsx)(n.strong,{children:"French"})," translations to a ",(0,l.jsx)(n.strong,{children:"newly initialized English Docusaurus website"}),"."]}),"\n",(0,l.jsxs)(n.p,{children:["Initialize a new site with ",(0,l.jsx)(n.code,{children:"npx create-docusaurus@latest website classic"})," (like ",(0,l.jsx)(n.a,{href:"https://github.com/facebook/docusaurus/tree/main/examples/classic",children:"this one"}),")."]}),"\n",(0,l.jsx)(n.h2,{id:"configure-your-site",children:"Configure your site"}),"\n",(0,l.jsxs)(n.p,{children:["Modify ",(0,l.jsx)(n.code,{children:"docusaurus.config.js"})," to add the i18n support for the French language."]}),"\n",(0,l.jsx)(n.h3,{id:"site-configuration",children:"Site configuration"}),"\n",(0,l.jsxs)(n.p,{children:["Use the ",(0,l.jsx)(n.a,{href:"/docs/api/docusaurus-config#i18n",children:"site i18n configuration"})," to declare the i18n locales:"]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config.js"',children:"export default {\n i18n: {\n defaultLocale: 'en',\n locales: ['en', 'fr', 'fa'],\n localeConfigs: {\n en: {\n htmlLang: 'en-GB',\n },\n // You can omit a locale (e.g. fr) if you don't need to override the defaults\n fa: {\n direction: 'rtl',\n },\n },\n },\n};\n"})}),"\n",(0,l.jsx)(n.p,{children:"The locale names are used for the translation files' locations, as well as your translated locales' base URL. When building all locales, only the default locale will have its name omitted in the base URL."}),"\n",(0,l.jsxs)(n.p,{children:["Docusaurus uses the locale names to provide ",(0,l.jsx)(n.strong,{children:"sensible defaults"}),": the ",(0,l.jsx)(n.code,{children:''})," attribute, locale label, calendar format, etc. You can customize these defaults with the ",(0,l.jsx)(n.code,{children:"localeConfigs"}),"."]}),"\n",(0,l.jsx)(n.h3,{id:"theme-configuration",children:"Theme configuration"}),"\n",(0,l.jsxs)(n.p,{children:["Add a ",(0,l.jsx)(n.strong,{children:"navbar item"})," of type ",(0,l.jsx)(n.code,{children:"localeDropdown"})," so that users can select the locale they want:"]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-js",metastring:'title="docusaurus.config.js"',children:"export default {\n themeConfig: {\n navbar: {\n items: [\n // highlight-start\n {\n type: 'localeDropdown',\n position: 'left',\n },\n // highlight-end\n ],\n },\n },\n};\n"})}),"\n",(0,l.jsxs)(n.admonition,{type:"tip",children:[(0,l.jsxs)(n.p,{children:["You can pass a query parameter that will be appended to the URL when a user changes the locale using the dropdown (e.g. ",(0,l.jsx)(n.code,{children:"queryString: '?persistLocale=true'"}),")."]}),(0,l.jsx)(n.p,{children:"This is useful for implementing an automatic locale detection on your server. For example, you can use this parameter to store the user's preferred locale in a cookie."})]}),"\n",(0,l.jsx)(n.h3,{id:"start-your-site",children:"Start your site"}),"\n",(0,l.jsx)(n.p,{children:"Start your localized site in dev mode, using the locale of your choice:"}),"\n",(0,l.jsxs)(r.Z,{groupId:"npm2yarn",children:[(0,l.jsx)(i.Z,{value:"npm",children:(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-bash",children:"npm run start -- --locale fr\n"})})}),(0,l.jsx)(i.Z,{value:"yarn",label:"Yarn",children:(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-bash",children:"yarn run start --locale fr\n"})})}),(0,l.jsx)(i.Z,{value:"pnpm",label:"pnpm",children:(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-bash",children:"pnpm run start --locale fr\n"})})})]}),"\n",(0,l.jsxs)(n.p,{children:["Your site is accessible at ",(0,l.jsx)(n.a,{href:"http://localhost:3000/fr/",children:(0,l.jsx)(n.code,{children:"http://localhost:3000/fr/"})}),"."]}),"\n",(0,l.jsx)(n.p,{children:"We haven't provided any translation yet, so the site is mostly untranslated."}),"\n",(0,l.jsxs)(n.admonition,{type:"tip",children:[(0,l.jsxs)(n.p,{children:["Docusaurus provides ",(0,l.jsx)(n.strong,{children:"default translations"}),' for generic theme labels, such as "Next" and "Previous" for the pagination.']}),(0,l.jsxs)(n.p,{children:["Please help us complete those ",(0,l.jsx)(n.strong,{children:(0,l.jsx)(n.a,{href:"https://github.com/facebook/docusaurus/tree/main/packages/docusaurus-theme-translations/locales",children:"default translations"})}),"."]})]}),"\n",(0,l.jsx)(n.admonition,{type:"warning",children:(0,l.jsxs)(n.p,{children:["Each locale is a ",(0,l.jsx)(n.strong,{children:"distinct standalone single-page application"}),": it is not possible to start the Docusaurus sites in all locales at the same time."]})}),"\n",(0,l.jsx)(n.h2,{id:"translate-your-site",children:"Translate your site"}),"\n",(0,l.jsxs)(n.p,{children:["All translation data for the French locale is stored in ",(0,l.jsx)(n.code,{children:"website/i18n/fr"}),". Each plugin sources its own translated content under the corresponding folder, while the ",(0,l.jsx)(n.code,{children:"code.json"})," file defines all text labels used in the React code."]}),"\n",(0,l.jsx)(n.admonition,{type:"note",children:(0,l.jsxs)(n.p,{children:["After copying files around, restart your site with ",(0,l.jsx)(n.code,{children:"npm run start -- --locale fr"}),". Hot-reload will work better when editing existing files."]})}),"\n",(0,l.jsx)(n.h3,{id:"translate-your-react-code",children:"Translate your React code"}),"\n",(0,l.jsxs)(n.p,{children:["For any React code you've written yourself: React pages, React components, etc., you will use the ",(0,l.jsx)(n.a,{href:"/docs/docusaurus-core#translate",children:(0,l.jsx)(n.strong,{children:"translation APIs"})}),"."]}),"\n",(0,l.jsx)(n.p,{children:"Locate all text labels in your React code that will be visible to your users, and mark them with the translation APIs. There are two kinds of APIs:"}),"\n",(0,l.jsxs)(n.ul,{children:["\n",(0,l.jsxs)(n.li,{children:["The ",(0,l.jsx)(n.code,{children:""})," component wraps a string as a JSX element;"]}),"\n",(0,l.jsxs)(n.li,{children:["The ",(0,l.jsx)(n.code,{children:"translate()"})," callback takes a message and returns a string."]}),"\n"]}),"\n",(0,l.jsxs)(n.p,{children:["Use the one that better fits the context semantically. For example, the ",(0,l.jsx)(n.code,{children:""})," can be used as React children, while for props that expect a string, the callback can be used."]}),"\n",(0,l.jsx)(n.admonition,{type:"warning",children:(0,l.jsxs)(n.p,{children:["A JSX element is an ",(0,l.jsx)(n.em,{children:"object"}),", not a string. Using it in contexts expecting strings (such as the children of ",(0,l.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option",children:(0,l.jsx)(n.code,{children:"