The basics - Internationalization with Next.js in 2024 (app router)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi my name is Paul and welcome to the first video in our series on internationalization and nextjs in this series we're going to take you from the absolute Basics which we plan to cover in this video all the way to fullon Enterprise level you're ready for anything type internationalization and I want to start off by discussing why we're making this series this is a fairly large topic and while there are a number of very good videos on the basics of internationalization in nextjs we haven't found anything that goes anywhere near as far as we intend to in this series and it's a pretty big topic and there's a lot more that you need to know about how to do this properly than just adding a low cal file or a number of local files to your project next I want to talk just a bit about the history of internationalization in nextjs and where things currently stand internationalization was released as a feature of nextjs in version 10 and that was about 3 years ago at this point at that point it was more or less built into the framework as a core competency it was uh first class citizen you might say and what that means is that even core elements of the framework like the link component and the router accepted alocal as pams meaning that the architecture of the platform or of the framework was aware of this concept and would do things on that basis now all of this changed when nextjs released the app router in version 13 as if this recording were at about 14.1 off the top of my head so the big change here is that while the documentation for next still referen say internationalization and gives you ideas about how to do it in your application it was pretty much removed as a competency of the framework itself and I think this was the right choice the reason being if you think about the functional component of internationalizing your site at least at its Basics all that really needs to happen at the most basic level of your application is that when a user arrive through route that begins with slen for instance you would show content in English whereas when a route begins with NL you would show them content in Dutch so that's not necessarily something that needs to be managed at the framework level especially if you want to customize it which is actually why in this series we intend to start from the absolute Basics and not use any external packages for internationalization because it's very important that you understand the absolute rudiments of how it works in your application therefore you have total freedom to make any changes to the behavior of the way your application internationalizes its content that you would like to make at any point so we're going to dive in here in just a moment after quick in for me as I said my name is Paul I'm the founder of render we are a custom product and software development studio if you have web application needs reach out to us using the link in the description that said let's jump in okay we are ready to scaffold out our next JS application I'm just going to accept all the defaults here we'll pop this open in vs code and real quick just fire up the app let's take a quick look and make sure that everything works as expected it does great so let's jump into the app directory here and go ahead and create a dynamic root segment if you don't already know a dynamic root segment will pass the value that you create here as a parameter to your root so we want to move everything but the icon into this new directory and let's go ahead and start making use of our new Lang parameter and we'll pass this directly to our HTML element to properly set the Lang attribute so what's going on here why do we have a 404 well we've told the application that we always expect for there to be something at the very root of the project by moving our most root most close to the root of the project layout and Page directory or page files to this Lang directory so we need to take our first steps on implementing this according to the next JS docs but before we do that I just want to show you a few changes I'm going to make on the configuration and TS config.js so so that we can easily use Alias Imports I'm just going to copy in something here so these are going to be where our constants and components live in this project it'll just make it so we don't have to look at all of this every time we import a component okay that said let's continue now as I mentioned nextjs does still have documentation on internationalization it's fairly brief though so we're going to grab what we need out of it and I'll just point out a few things that I think are not quite optimal on how this is set up right now but the first thing we need to do is create a middleware TTS file so we're going to grab this and as you see here we need to install a couple of packages so let's jump back over here okay fire up the app again actually before we do that we're going to see that after we do that negotiator is still going to complain so we want to install these types as well and now we'll fire up the application again okay no more type issues there so jumping back into the nextjs stocks we're going to run into a bit of an inconsistency here uh they just document that you can manage all the stuff that's going on here at the top of the file to match the users's local in a different way uh this I believe used to be included in their next in the the documentation it is no longer and so I'm just going to clean this up a little bit here and where they were previously calling get local we're just going to call match okay so let's see if things have improved all right so we see our content again but you see that we've been redirected to for- us now the reason that happened here is because we check if the path name has a local and if it does have a local we're just going to return the request if it doesn't we're going to redirect the user to the page with the local that matches their browser note of course that we are excluding this middleware from running on all of the static next resources like CSS and JavaScript okay so let's note a couple of things here see how we have the strings hardcoded into the application that's fine and it works but there's actually a better approach that we can take so let's take a look at that now the first thing I want to do in our app directory actually I'm going to do this at the root of the project doesn't make a huge difference actually but it's just preference I'm going to make a constant directory and in it I'm I'm going to create a file called locals. TS and in this file we're going to export two variables one of them is going to be local which uh locals which as you can I'm sure imagine is going to be an array but we're actually going to make this an array of objects and this will make more sense in future videos for this example we are going to be using English and Dutch and then let's also declare what our default local is and for this project it'll be and then uh English I should say we are going to export both of these okay and then we also want to make an ITN config and we will just paste this in here now you may wonder why we have similar information declared in this file as we do have in our constants file that'll make more more sense as we go through the project but for now just think of the locals in the i8n config here as being a smaller version of the information that will exist in locals as we continue to expand the project so we want to go ahead and import default local from our Local's file and we want to import i8n from our config and we'll get rid of the of the Imports that we no longer need and we'll just need to update these two as coming from i n and we're set we're in exactly the same shape as we were before you can see that we have our application running on for SL NL and for slend great now one thing to point out here is that we have already made a decision in that we are deciding that there is effectively no default local for the the project in that we go to local host 3000en for the English content and/ NL for the Dutch content you have to decide what's appropriate for your application the setup that nextjs gives us in their documentation is great but I want to show you an alternative okay so I've pasted in here another option for how we can handle things if we decide that we do want to have a default local and so for instance not show slen if the user is browsing the site in English we can do this here so basically we are going to have two if statements that make a distinction between a redirect and a rewrite if you don't already know a redirect is when you change the path that's actually shown in the address bar of the user whereas a reite allows for the content of the address bar to be anything you like but it tells nextjs that the request should be handled by the part of the application that you are rewriting to so for instance if a user comes in here and and they are on a page whose path starts with a default local or is the default local we're going to do a redirect we emphasize this in the comment here a redirect to send them to that same path without that default local as part of it and then this is going to rerun again because this request will come through and it's then going to look and see if the path path name is missing is missing a local which now it is and so it's going to say okay let's now do a rewrite to add en for that request so that that is then handled by the appropriate part of the application and in so doing we now have a default local where English for example is showing at Local Host 3000 and Dutch if we were at this part of the application would be showing here because we're at for/ NL okay so our middle work complete let's go ahead and prove out our assumption here that we do in fact have the Lang available in layout and in page so we'll just do a quick console log here in layout and we'll do a similar one in our boilerplate page is going to come in on pams now let's check out our log we'll reload the page here and see that I have made a mistake in the layout which is to try and grab Lang directly off of props instead of off of pams and now we see that our language is showing in both page and layout okay let's continue so we verified that our Lang is available now let's create our dictionaries we are going to add a new folder here in Lang call it dictionaries and while we're at it I'm just going to create another component that we'll be using soon called components and one last addition here diaries. TS okay so in dictionaries we're going to create our two files and I'm going to skip over this I just want to go over this in concept because it's time to get into actually the application here so the point is that there is a Json file and it has the content of our two languages English and Dutch in this case and then we're going to create this here and this file and it's going to complain at us so we'll create these real quick and let's jump back over because this is going to have a type issue so for now now we'll just solve this with any and then this is going to want to be a string okay cool we're in good shape there onward so we want to go ahead and grab get dictionary in our page and we want to invoke this and get our dictionary we also need to make this async okay so we don't actually have much in our dictionaries right now they're looking a little empty so I'm going to hold off on actually firing this off and let's get to scaffolding out our content all right now that we've gone as far as an nextjs internationalization Doss can take us let's take a look at the application that we're going to be building we have here a very simple e-commerce layout with a header a local selector a couple of products add the C buttons and a footer and note that we can switch between locals by using our navigation here so let's see how we build this okay so let's just really quickly move our props up here be a little bit more readable and then we'll pass these and then before we jump into actually making our layout let's do one last optimization here so we'll just add generate static prams here to make sure that the application generates English and Dutch as prams for our layouts and so now we can go ahead and create the components for application we will start with main layer and I'm just calling this main layout to distinguish it from layout as we're working in the editor here and then we also want to create our header. TSX and our footer. TSX okay so I'm just going to paste this in here because there's a good bit going on so we get our dictionary the current Lang we've typed those out to a certain extent and then we are going to pass those to our to the div inside of the links here and we're just going to do that a little bit of styling that you saw where the non-current local is going to be a little bit smaller other than that it's pretty straightforward we pass in our sweet logo and uh then we'll move on to the footer and so here's our footer right now it's pretty straightforward note that this text has not been translated we will come back to that now that we have that we can jump over to our main layout and we'll import our header and we'll import our footer and then we're going to create our component okay so here we're going to get a couple of props we're going to get children of course this being a main layout we're going to get our dictionary we're going to get the Lang and then we will type that out we're going to call it props children another react. react node DCT we're leaving as any for the time [Music] being L there a string okay then for the markup I'm just going to replace this div with one with a few Tailwind classes and then we're going to pull in our header and we'll pass the props that it needs which are going to be dick and Lang okay and then we'll do similar thing for the footer but it doesn't need L and then we're going to have a div that wraps the rest of our layout which looks like this okay so our main layout is there so now let's jump over to our page which still has our starter content in it so I'm going to uncomment these we actually do want to get our dictionary now and we need to get rid of this next JF starter content so we're going to create a div so we're going to paste in here in H1 with a few Tailwind classes and then we're going to do dict do products. catalog and then we'll put in a new div here with a class name of flex H fit and gap of six and then now we need to create our product components so let's go ahead and do that we're going to make product. TSX we are going to need need a button. TSX okay and in our button. TSX there's not a whole lot going on here we just have some Tailwind classes and then we use another translation key so we'll save that close that one up okay and then we are going to need a little SVG for the icon that you saw in the layout so that we can import that here and in product we're going to import image and we're going to to import button and we're going to import our image make our component grab our props type them out ID is going to be a string okay okay so we are going to just paste in a few lines of code here because there's a lot of CSS classes so the gist of what's going on here is that we have an xjs image with our image source and then we grab a few more props and we are passing the ID which we got which we'll select which product we're interested in and then we have our button which we saw a moment ago note that I have forgotten to translate the alt text here for the image which Speaking from experience is really easy to do so just try and keep an eye on that make sure you always include that so we'll do it dot alt text okay then we will come back to our page. TSX we'll import product pop that in here and we have two products in our store and so let's go ahead and use our component but first actually before we do that let's take a look at our layout let's see what our progress is what's going on here well we're calling our dictionary but we don't have any created yet so let's do that real fast so I'm going to go over to dictionaries here and this is where our translation content is going to go English it's just going to look like this and Dutch is going to look like this all right so now we should be able to take a look at our content and it's pretty straightforward but we're getting there okay now that we have all of our components created we can go ahead and import our main layout and let's use it so we'll wrap children with it and then we need to pass a few components or a few prams rather all righty we should be looking better as soon as we grab the dictionary in our layout too because of course we need it there as well we will also need to make this layout async now we're kind of getting there let's add a few classes to the HTML actually one class to the HTML which is just going to give it make it the full height of the page H full and we will extend the class that is currently on the body to add H full there as well take another look boom we got our full page layout now let's make this a little more interesting okay so let's make use of our product component now we are going to need to pass it a couple of prompts we're going to need our dictionary we're going to need the Lang no sorry the ID rather uh which for the first one here just going to do product one obviously if this were an actual you wouldn't be coding this part up quite this way but we aren't using an actual product catalog so I think we can let it slide oh I missed typing our pams okay all right so oh and we can get rid of the log here as well let's take another look at our layout hey there we go we're looking pretty good okay so now we have the full function functionality of our application but this footer is actually still looking a little shabby I don't know if you noticed it didn't translate when we switch languages so let's come back to that and we will finally use our dict here as well so we're going to do dict do footer. all right and our footer is looking all right let's check out Dutch what happened here well let's look at what's going on so why you weren't looking I actually got rid of the translation for Dutch for the footer because I wanted to make this point that this is one of the weaknesses of this approach if you forget to include a key especially a nested one for any given local your whole page the whole view is just going to explode on you so it's definitely important to test if you are going to take this approach there's also another weakness of this approach which is let's get rid of this log as well that we have to pass our dictionary anywhere we want to use it so we have to pass it from Main layout to the header and the footer and then we pull it in on the page as well we grab our dictionary we pass it to the product and then we pass it to the button obviously this is a pretty simple application and maybe that's not terrible depending on what you're doing this might be absolutely fine but if you have many nested components that can get tedious and hard to maintain and tedious uh pretty quick so that's something that we're going to be looking at in the next video so let's go ahead and fix our Dutch translations and okay we're back in shape all right this is looking great so we're just about ready to leave this here I just want to make one final point and that is that this entire application so far is using react serve components we are using the new style of internationalization in nextjs and so that's pretty exciting we're using lots of the great new features of the app router and the most recent versions of nextjs so so we are going to want to take this quite a bit further though for instance let's have another look at our local selection we have two languages in here and that may look okay for the time being but what about when we want to add a third language or 10 languages or more this option is not viable so obviously we're going to need something interactive here which means using use client and so we will also be getting into that in the next video we have a pretty good starting point here this is definitely the basics of Internet nationalization in nextjs but you can probably already feel it's pretty basic and so you have to think about in terms of putting your translations in these Json files what about when you have many locals or even more to the point what about when you have many pages on a large site okay maybe that's manageable what about then when your layout changes or your client decides or you decide if you're the client you decide that you want to change everything well that's going to be a pretty tedious somewhat error prone change for you or your Dev team which means that we're going to need a much more robust way to manage all of this now we will start to get into that and much more in our next video so make sure that you stick around for that subscribe give us a like if this video was useful for you and make sure you come for the rest of the series because there's really going to be a lot here and our goal is that it helps as many people as possible thanks again and we will see you next time
Info
Channel: Rendr - Crafting Web Platforms
Views: 3,286
Rating: undefined out of 5
Keywords: Internationalization, i18n, next.js, react.js, app router, react server components
Id: _airUG9o97w
Channel Id: undefined
Length: 25min 26sec (1526 seconds)
Published: Wed Feb 21 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.