React Multi Language App - i18next Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so you created a react app but you wanted to add to it multiple languages and of course allow the user to switch between these languages if they wish to do so but you couldn't figure out how to do it easy in this video i'm going to show you how to create this thing right here which you might be thinking what is this this is just a simple page with a piece of text that says welcome and some silly text here and an icon and you would be right it's nothing but that but what this does is if i click on this icon i get this list of languages that are available and let's say if i wanted it to be french i'm going to click here and voila it's in french now and also if i wanted to have it in arabic which is a right to left language it will become now in arabic and it will indeed be right to left and the icon now is on the left lovely on top of that i'm going to give you two little bonuses one is how to change the title here as you can see now it's in arabic and if i switch back to english it's now in english and also how to change it through the url so if we go to the url and we type here slash ar now it's back in arabic and if we type here fr and now it's in french and this also persists so if we just remove that and if we refresh the page it's still in french so the language setting is actually being persisted on the user's machine via a cookie okay so that's that for my cringy demo so let's actually jump into the code so let's first create this react app so here in the terminal i'm gonna run mpx create dash react dash app and let's call this what do we call it let's call it localization because that's what this is and of course i misspelled that so let's fix that and i'm going to use a template so let's say dash dash template and say clean dash cra to give us this uh react app that doesn't have like these extra files that we will not use we just need the simple react app let's let that install the dependencies and let's take a look at this tool that will allow us to do this so we're going to be using i 18 next and the react implementation of it in particular so this is the utility or the framework that will allow us to initialize this configuration and and then set up our different language texts and then allow us to switch between them if the user changes the language and that's a very basic way of explaining it so if we scroll down here it shows you how to use it inside of the jsx but let's ignore that for now and actually let's go to getting started so here it tells us we need to install the i18 next itself and the react implementation of it so let's copy this command we don't actually need save anymore just copy that and if we scroll down and here it shows us how to configure it so let's actually paste that command first or actually let's open that directory that we created so say code localization and actually that will open a new window so let me close this one okay so now we can paste that command so in our terminal inside of this project let's paste that npm install command and let it install those two packages and let's go back to the docs and by the way i should have told you already to go to react.i18next.com and let's actually copy all of this from the i18 import down to right before the react dom render call copy all of that and let's go to our source directory inside of up or actually inside of index.js and then let's paste everything under the imports and we want to keep respecting best practices and let's so let's cut these imports these relative imports and move them down here so here what this does basically is that it imports i18 from iot next and then it initializes it using this init react i18 next from the react ion implementation so it passes this configuration to react i18 so that we can use it and then it initializes it with this basic config so what you see here we have this resources object which includes all the languages that we have and right now we only have english so here we have this translation object which contains this welcome to react key which corresponds to this value and then we have this lng for language which sets the language to english here and then we have this fullback language which is a good thing in case the user selects a language that is not supported this will be put instead and we have this interpolation thing which i believe in react is unnecessary so i'm just going to remove it and then we have this app which by the way this will override our default app so let's actually comment our app import for now and then keep this one so here we have this use translation hook call which is a hook that we obtained from the react i18 library and then it gives us the t utility which is a function that we use and then we pass it a key from the translation keys here and then it will fetch the value of that key depending on the selected language let's take a look at what this means now right now we only have english so let's actually add a different language to test this so i'm going to add a comma here and then just duplicate this and i'm going to add french for now so let's say fr so keep the exact same key name this is important and now let's translate this to french so this in french will be welcome to react so this will be ah react a react i 18 next and surprise surprise i speak french too so now actually let's save this and let's start it first so let's say npm start and this should just show us the welcome to react and the i 18 next message so and there we go so we get welcome to react on i18 next and we can actually test changing the language manually right now so what we can do we can go to our index html inside of the public directory and just change here in the html tag change this lang attribute from en to fr for french and let's take a look at it refresh okay that's not changing because i forgot to give the language because right now the language is hard coded to be english so let's make it find the language based on our lang attribute so that's easy we can use the document object to find this value so here instead of just saying hard-coded english we can just say document dot query selector and we want to get the html element and then we want to get the lang property or attribute so save this and now if we refresh there we go we get bienveni our yacht so it's in french now because we put afar here and if we change it back to english and we refresh we indeed get welcome to react and now it's in english cool now a better way of doing this because the language is not always just in the lying property inside of html it can be in many different places and obviously the lang property here is always served the same from our file server that's given this file and we can't have user settings stored in here obviously so we can fetch everything manually but we can also use a utility that makes it easier so let's go and google i 18 18 next browser language detection and yeah so we get this package this uh i18 browser language detector and this gets the language from around what is this eight or nine different sources without us having to write one line of code and as you can see here we can just install this so let's actually just grab the package name or you can just grab the command actually and we can go to our terminal and i'll open a new terminal and paste that there and we can configure it doing the following so we can import it like that and say dot use just like we did with the i18 next react implementation so let's paste that there and then let's copy that and here we can just say dot use and we can chain as many of these um are they middleware they feel like middleware or these utilities i guess so we can configure this by passing an object inside of this initializing or init options so here we can say detection and you can see by the way in the documentation here what you can pass and it tells you that you pass it as a detection object and here you see there's an order which tells the utility which setting to prioritize so you could have multiple ones but you can prioritize let's say the cookie because that's the user setting and if you can't find the language inside the cookie you actually revert to whatever comes next so i'm actually going to copy this order key value per and let's go to our config here we'll say detection and inside here i'm going to paste that and i'm actually just going to keep actually for now let's say html tag comes comes first so that's what we've been using and i'm gonna keep i'm gonna keep cookie and also local storage and then remove everything else except for path which will come later and i'll keep sub domain as well even though we can't test that locally i'm keeping it because it's a common way of giving language to a site so now we can actually remove the lng key from here and save and now let's refresh our app okay nothing changes because it's still in english and now if we change to fr it should automatically detect that and there we go it automatically detected that now nothing has changed from what we had earlier but now we can say inside a detection we can say caches and here we can specify different places where we want this language setting to be cached in for our user so for this i'm just going to use the cookie one for now so i'll say cookie as a key here and now if we refresh and we open the dev tools we go to application so here we actually have it in local storage as well and then if we go to cookies we go to localhost 3000 and there you go we got i18 next and the value is fr and of course one more time if we change to en and we save and we refresh that cookie changes so this package is indeed updating the setting based on the user setting now if you go back to the config you'll see that we have here we have everything all of our language information inside of this resources now this is a bad practice because this app can grow to be really big and we can have like so much text and obviously this will be a bad practice to store all of it here because this file will be gigantic first of all and second of all if the user wants to visit the english site they will still have to load all of the different languages which is not ideal we want to be able to load just the language that the user specifies so that we save on bandwidth and the way we can do that we can use another package called i18 next http backend so if you go and google that i18 next http yeah this one http backend and this is just a utility that allows us to load the different language files from any source that we wanted to load it from so let's copy this install command and let's go to our terminal paste that there and now we can actually outsource the translation data into files and then load them once the app is loaded so let's uh what we can do is we can copy this uh english translation object just copy that or cut it and then let's go to public so here let's create a file i'm going to call this actually let's have it inside of assets so say assets slash locales slash and here we'll have the file inside of the language that it pertains to so here we'll say en for english and then here we'll say one last slash and we'll say translate or translation dot json and then paste that there let's rename this because this is not the very json friendly name so here let's say welcome underscore to underscore react and change these single quotes to double quotes because this is a json file and remove this comma and save and we can copy this and then create inside of locale a new file fr slash translation json and then paste that and now we need the french sentence for this so let's copy this or actually just copy the text inside of it and then go to the fr translation and then paste that there and save and now we can actually remove this resources key and now that we have i18 http backend installed we can use it so actually let's look at the docs yeah let's just grab this import call paste that there and then we need to use it so here we can just chain another dot use and then say http uh what do we call http oh yeah it's called http api there so let's just say http api and we can configure it inside of the config with this key uh what is it yeah this back end key and then we have all this different config which we'll get to in a moment so here inside of the init call inside of the options here we can say backend and then open an object and here i'm just going to give it one thing which is this load path which tells it where to find the translation files now this is a relative path because we're serving the files from within the same project so from this react file server as well and you can also obviously load these from your backend api or from s3 bucket or from anywhere but in this case it's relative so we can actually just copy this load path and then paste that here and here we can point to where our files are so here i'm going to add a slash assets and then we have locales and then here we have this lng which will tell it depending on the language where to look so we have en fr that will take that place but here we don't have this ns which is namespaces we're not using namespaces so we can just replace this with translation.json now let's save and if this works nothing should change in our app so let's refresh okay so we get app suspended while rendering and this is because this package tries to use suspense to show some placeholder before our translation files are loaded we can get around this by saying actually there's a key here use or actually i think it's uh yeah it's inside this react object and then we'll have this use suspense and we can say false and then save and now for refresh there we go we get okay we get welcome to react and that's not correct because that's the name of the key that we gave and because we changed that key actually let's change it here so here we'll say welcome and then underscore to and then underscore our react and then we refresh there we go we get the english one and actually we can change manually this cookie value to fr and then refresh the page okay that's not working i think maybe it's oh yeah because it's fetching the html tag one and then when it finds the value there it overrides it and then saves the cookie we can actually change that and we can set html tag to be second and then cookie first so now if we manually change the cookie value so let's rename this so edit this value to fr and then refresh there we go now it's in french because it's fetching the cookie first before the html tag and it's now actually ignoring html tag because this is more priority cool so now if you look at network as well you'll see that it's loading translation and if you refresh it's only gonna load okay it's loading both um i believe because we're setting it to french so it's gonna load the default one and then the french one so let's change it back to english and see so english refresh yeah you see now it loads only the english one because it happens to be the fallback one as well so obviously we don't want to be changing the language manually through cookies our user will not do this so let's implement the way for our end user to change it through the ui now you know me guys i don't want to work with something that's really basic looking so i'm actually going to install bootstrap in this to make it look at least a bit nicer and also to have a drop down to use later so let's go to get bootstrap.com and we can just copy this uh install command so here let's go to our terminal and do npm install bootstrap at next cool and now we can include bootstrap so let's go actually here inside of our index.js here at the top we can just import the css and actually the js as well so let's say import bootstrap slash dist slash css slash bootstrap dot min dot css and then duplicate that and then this will be the js and this will be bootstrap.js so i'll keep put that there and then the css there and now we have bootstrap so i don't think we can see anything oh okay we need popper js because it's a dependency of bootstrap so let's copy that and then in our terminal let's say npm install excuse me popper.js or add popper js core minimize that actually we need to wait for it to make sure that it's working all right so now pop is installed and bootstrap is installed and working included that's cool so now let's um actually prepared these uh files already so you can go to this git repo i'll put a link to this in the description and go to the public directory and then copy this assets file which our folder which includes a couple of pieces of text in these three languages that i'm gonna use to demonstrate this app in this video so you can go ahead and copy this entire assets file and then put it inside of your public here i have this on my computer so i'm gonna do it off-screen okay i've done that now so we have this three so we have the arabic one the english and the french so we'll use this to test all right so now inside of our index.js let's bring back the app import and then remove this app from here we're gonna use the actual one from the app.js file and then save keep everything else the same and actually here inside of the options for i18 next we can say supported languages or supported lngs and then we can give a list of our supported languages and in this case we have not env en for english and then fr and then ar for arabic so save and now let's go to our app.js so here let's change the class name of this to container and then inside of here i'm going to have a div with a class of d dash flex to give it a display of flex and also let's give it the class flex column so stuff goes top to bottom and also align items start and i'll explain why i have this later so here i want to already use something from our translation files if you look at them we have this we have this app title or actually another title we have the welcome message i want to use this at the top so here to be able to use that we need to do the same that we did here so actually let's grab this import and remove this use translation because it's not being used here anymore and then save and then in the objects paste that and then remove the init part of it and then here at the top of the component we'll say const t equals or actually t the structure t from use translation and call it as a hook like that and as we did earlier we can just say t and then pass it the key actually this needs to be inside of an expression to be able to say that because it's not just a piece of text so here we'll say welcome underscore message now let's save and now let's look at our app refresh there we go we get welcome because that's the english one i want to remove this dark background so actually i'm just going to get rid of this index css we don't need these styles and of course let's get rid of the import inside of index js so that it doesn't crash so now let's refresh cool now we get the classic white background let's go back uh to our app.js and here actually i want to make this a title so let's say header1 and let's just style it while we're at it so let's say class name give it font weight normal so it's not too bold and then give it some margin on bottom mb3 close that opening tag and then bring the closing tag after this and also i want to do something clever here so let's do a paragraph and i want to show you how to use a value with a dynamic value inside of it so if you look at the translation files let's look for example in english one there's a key here called day since release and this says it's been and then this number of days days since this video is released so i'm going to use this as an example to show you how to use a dynamic value inside of your text because you're going to need to do this in your app so to use this in a simple way we can say t and then do the name of the key which is days since release and then we need to pass it that value here now let's calculate that value you know me guys i'm a bit extra so i'm going to do something that's kind of clever here it's not it's not that clever it's just silly so here i'm going to say const release date of this video that you're watching which is today which is the so let's say new date and then today is the 7th of march so let's say 2021 03-07 i want to find the difference between them in days so let's say const time difference and the difference will be new date which will be right now of course for me it's the same day but probably for you would be different and we'll say this new date minus release date and this will be just as a number in milliseconds so let's convert that so i'll say const and i'm going to name it the same as here so number of days like that so let's say const number of days snake cased equals math dot floor and let's say time difference and we convert this to days so we'll divide it by a thousand to make it into seconds multiplied by 60 to make it into minutes multiplied by 60 for hours and then multiply by 24 for days and now we get number of days between that date and now which in my case should be zero and now we simply pass that object here as the second parameter to this t function call and now let's save and let's look at it and there we go we get it's been zero days since this video is released because it's not released yet it's going to be released later today to show you that that's working i could just change this value here and let's say 10 and now it says it's been 10 days all right so i'm going to remove this now let's add a way for the user to change the language through the ui like we said earlier and for this let's go to the docs of bootstrap and so go docs and components i want to use the drop downs so drop down right here so drop downs we can just grab this so just grab this um actually we could just click copy here and then i'm going to put that in its own div here at the top of the container and also give it display of flex so d dash flex and then give it justify content end so that it's pushed to the right tab that and then paste that drop down in and of course here what we want is instead of just obviously action another action we want a list of our languages inside of here so here let's create that uh array i'll create an area here at the top this will be our constant languages array so here we'll say const languages equals and do an array and these will be objects because we need multiple properties and first thing is i'm going to say code and i'm going to do them alphabetically so we'll start with french so the code for french is fr and by the way these are iso codes i'm not just making them up you can google them to find the ones you need so here for the name of the language we'll say name which represents the name of it on the ui and actually we can google this so let's say let's google the name of the language because french has this special c character so let's say actually let's say translate and detect language let's say french and from english to to french and then here we have actually it's not frances it's actually francais this one here so let's copy that and then paste that here make this capital f and i'm also going to add something else i'm going to add country underscore code because i want to show the flag that corresponds to this language to make it easier for the user to find that language and typically french is associated with the country of france and the code for that is actually fr2 so let's put a comma here and then duplicate this two more times so this will be english and obviously the name is english and the country code typically english is associated with the uk so let's say gb for great britain now of course these languages are spoken in other countries we're just gonna use the most typical country and this will be arabic and the code is ao and then the name actually we want to have the name in arabic as well so here we can say in the translate arabic and then translate this to arabic and it's actually not this this is an adjective we want this which is the noun of the language so actually i'm just going to click that and copy this oops copy that and then paste that there and then the country code i want to use saudi arabia which is the most typical it's got arabia in the name so save this and now we have our languages so now we can loop through those and show them as options in our drop down so here instead of having these uh hard-coded allies i'm going to remove two of them and keep one and then do an expression here and say languages dot map and we can actually just just destructure the code the name and also the country code and actually these need to be inside of parentheses so parentheses like that and let's do an arrow and then do parentheses so that we can return and we're going to return this li so drag up here and because we're looping through something in react it's recommended to give a key so here we'll say key and the key will be country code because this will be unique and then here instead of using an anchor tag i'm going to use a button because the react complains if you have an anchor tag that has a link that doesn't go anywhere so here let's remove this href prop or attribute and actually these class should be renamed to class names so select all of these and then remove and add actually just add name at the bot um at the end and inside the button we're gonna do curly braces and say name to put the name of the language and to be able to show the flags we need to install this dependency so say npm install and this will be flag dash icon css which is this library that has all the flags that we can use as css classes so here before the name of the language we can say let's put a span here and let's give it a class name and this will need to have a flag icon class so flag dash icon and then flag dash icon and then for example if you wanted to do uk you'll say dash not bg dash gb but we want this to be dynamic because it depends on which country we have here so here let's replace this with curly braces and then replace that with backticks and then replace this with a backtick as well and then close curly braces and then here instead of gb let's do dollar sign curly brace and then concatenate country code and that's why i did this country code thing and also let's add here mx-2 to give it some margin on the side so that it's not right next to the text and here let's add extra parentheses and save and now let's take a look at our app go we get this drop down button and if we click on the drop down okay we don't get the flags because i forgot to include the actual css so let's go to the index.js and here under the bootstrap we'll say import and import from flag dash icon css slash css slash flag dash icon dot oops dot min dot css i already looked look this up i don't know this off the back of my head so save and refresh i mean you don't need to refresh it's just the habit of mine so click the drop down and there we go we get franci on english and al arabiya cool and we get the flags now of course these buttons don't do anything right now so let's make them work and i want to change this to an actual globe icon instead of this ugly button so let's go to actually now bootstrap has icons so if you go back to the homepage you can see here bootstrap icons and you can find so many cool icons let's do globe there's this um which one yeah i want this one this first globe one now you can use the library itself and then do this bi bi globe but i just want this one icon so let's do download svg and i'm actually just gonna i opened with uh chrome let's drag that into our project so oh it's actually just going to open it okay whatever i'll just put it as text so copy that and then instead of our app.js actually actually i'm going to create make it into a functional component in case we need to update or change stuff so we'll say here const globe icon equals and then do a function that returns actually just do parentheses and then paste that there and i want to be able to specify the width and height dynamically in case you want to change them so here we can say width like that and then height oops height like this and then here we're going to take them from the props so we'll say width and i'm actually going to say equals 24 here to give it a default value in case we didn't specify any so here we'll say height equals 24 as well and now we can use this globe icon inside of here inside of this button so instead of saying drop down button we're going to say globe icon as a component like that and of course you can give it height and width but if we don't it's going to get 24 and i'm fine with that and also i'm going to change this class name from btn secondary to btn link so it doesn't have a background so save and let's take a look at it so let's go here refresh it was already refreshed so here we have this globe there we go we click on it we get our languages and it looks much better than an actual button so now to get this to work we can simply say uh where we have this button when we click this button we need to change the language we can say on click and then give it a function that is a callback that says actually we need to import i18 next so here at the top let's say let's import i 18 next from i 18 next so here where we have our on click we can simply say i 18 next dot change language and then we can pass the code that we have from here so now let's save and this on its own should work so if we click on here now and we click on french there we go it's changed to french and if we refresh that's still in french because it's getting it from the cookie cool and if we change to arabic now it's in arabic now if you refresh you briefly see that it says welcome underscore message and also the text here will have the names and the keys that correspond to the values so to remove that behavior we can simply actually go back to the index.js and here we can remove this use suspense false and we can actually use suspense to show something when the language hasn't loaded yet so here we can import because suspense now is part of react itself so from react we can import suspense and here in our react render or react dom render call we can wrap this in a suspense component and put all of this inside of here actually that comma needs to be here and then now we're going to say fallback and then give it some fallback markup actually i'm going to put this here in its own variable so let's say const loading loading markup and this will be just a div and let's give it a padding on the top and bottom so p y 4 and then give it text center and inside of here we're going to have let's say an h2 and then say loading dot dot and now for the fallback we're just going to give this loading markup so loading markup save and now if we refresh there we go we get loading in the middle before it actually loads the text and it doesn't show us those original key names cool and to change the direction as you can see it's in arabic but it's not right to left that's easy we can actually set a default direction so if you go to index.html we don't need to do this but i think it's a good practice so for our body we can add an attribute here the which stands for direction and then give it ltr for left to right for default and we can go back to our objects and actually for languages that are right to left we can add another key so in this case just arabic and we can add the here and say right to left so rtl rtl and now we can first when this loads so we can use use effect so let's say use effect and make sure that it's imported from react and here we'll have our callback and this will run when the page loads and it will run again once the language changes so we need to detect that actually so we need to get the current language first so we can actually use the js cookie to access that cookie so let's open the terminal and say npm install js cookie which is a package oops i misspelled that jscookie so this is a package that will allow us to manipulate cookies on our client and here we just need to get the current language code so actually let's import this at the top so we'll say import from js cookie let's call it cookies so here the top let's say const current language code equals cookies dot get and the cookie is called i 18 next and we get the value but if that doesn't exist we can have we already have a fallback but let's just have another safety mechanism here and say or english or en and now we need to get the language from our language array based on this code and that's easy we can just say const current language equals languages dot find find language where language dot code equals current language code and now we have access to that and now here inside of our user fact we're going to say document dot body dot direction or de equals current language dot the and if that doesn't exist in the case of french and english we can say or left to right you can actually add this here but i think it's more concise to do this we only get it if it's right to left otherwise we revert to left to right because there's only two options and now we can give this current language as a dependency for our use effect so that every time the language changes the direction changes as well so now let's save and now let's look at it so there we go so we already switched to right to left and if we switch to french we are left to right and again if we go back we are left uh right to left and of course english is left to right as well cool so that's done uh one little thing is that here we don't have an indication of what the currently selected language is in the drop down and we can show that by going to the drop down here in the button we're just going to say disabled and the condition will be if code which is the code of this current element equals current language code and that's it so now if we refresh or we don't refresh we get that english is actually grayed out and uh if we click it the drop down goes away but nothing actually happens but the flag is still not grayed out so what we can do is can have a quick and dirty way of doing that which is here for the span we can add a style prop and this is an object so and we can change the opacity and we can actually use the same condition here so copy that condition and then paste that there and then do a ternary so if that's the case that means this is disabled let's give opacity of 0.5 and then otherwise so colon 1 otherwise it will be completely opaque so now there we go so now the flag is actually grayed out too and if we click on french there we go french flag is grayed out as well and let's add a piece of text at the top that indicates that this is where you change the language i already prepared a key for that called language oops so let's reopen up js and let's add that there before the loop here we'll say ally and underneath it will have a span with a class of drop down dash text or actually not that item dash text and then tap that and inside of here we'll do an expression and then we'll use the t helper and then we'll pass it the key language so that we can get the word language for each language so now let's go back there we go we get long for french and then in arabic we get lula cool and in english obviously we get language lovely and one final little thing which is the title of the document that's easy we can just inside of the same use effect call we can say document you can use something like react helmet for this but i'm just going to change the title of the document so it'll be kind of overkill to use it so i'm just going to say document.title equals i know we can actually use the t helper here as well by the way so we'll say t and we already have this up title here so we'll say up underscore title and react will uh kind of warn us that we need to put t in the the dependency array so let's actually put that even though it never changes anyway so now let's save and there you go so we in english we get title and in french we get which is title and as well in arabic we get on one cool now the bonus thing that i wanted to add is allowing the user to do something like this slash ar and tell the app to be in arabic which is not working right now and that's actually pretty easy and it's already in the language detector options it's this path option here the only difference is we need to make it more priority or higher priority than cookie for it to work so now the highest source of truth is path and then cookie and then if none of them exist it will fetch from html tag so let's save this and now if we run this there we go it's actually in arabic and it actually persists the cookie to save the option as the language is arabic as well because if you go to cookies so application cookies now the value is ar so now even if you remove that it's still in arabic and of course it works for french and now it changes the value of the cookie to french lovely alright so that's it for this one please make sure to like this video and of course subscribe if you haven't done so yet i hope you learned something new in this video and you enjoyed while doing it thank you very much for watching and i will catch you in the next one bye
Info
Channel: Classsed
Views: 17,096
Rating: 4.95574 out of 5
Keywords: react localization, multi language react app, i18next tutorial, i18next-react tutorial
Id: w04LXKlusCQ
Channel Id: undefined
Length: 38min 35sec (2315 seconds)
Published: Mon Mar 08 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.