Internationalization in NextJs 13

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we're going to talk about internationalization in Nexus 13 app router we're going to build a simple app together which has two pages and about page and a home page and we're also supporting two languages or two different locales English and German so by clicking on these links if you're going to be redirected to a sub path this is a pattern that we're going to learn there is a different pattern which is a domain routing which you would just redirect the users to a different domain or subdomain we are using the subpath strategy where we're just redirecting the user to a different sub path of our domain in this case this dot d e is representing Deutsche or German which takes them to the German version of our site now let's just jump back into this little note that I have here so if you understand the parts and pieces involved in implementing internationalization in extras 13 specifically in the app router and then we're going to actually jump into the code and build that app that I just showed together now internationalization refers to serving up content in your users preferred language this is typically coming from the accept language header from the browser depending on the country that they're living or the language preferences that they have set up inside of their browser now this process involves two different parts the routing part and the actual localization which is just a translation or localizing that string that text that you're actually showing to your users now the routing which is handled by next.js has two different strategies as I just touched on you can either use the path routing strategy or the domain routing strategy now in the path or the subpath routing strategy you're going to redirect the user or put the Locale in the URL path so for example you have for slash blog as your default route and then you would have four slash FR for slash block which is for French or NL which is for Dodge in Netherland or in the case of our app using Deutsche or German for Germany now in the domain routing strategy you're actually redirecting the user to a different domain or subdomain of your application for example example.com would be your default Locale maybe in English for French you just redirect them to example.fr or dot nl4 Dodge in the example that we just saw together we're going to implement subpath routing but it will be similar for domain routing because this is all happening inside of a middleware that we're going to set up together now one one thing that I want to note before moving forward is the app router in Nexus 13 does not have a built-in support for internationalization just like how the pages router had you could have set up your locales that you wanted to support in your next config in Nexus 12 in the pages router for now the app router doesn't have that but the good news is that we can actually implement it very easily using two packages and a middleware which we're going to see together now the second part or piece of this internationalization is localization as I just mentioned and this is the kind of translating your texts your strings into that language or that preferred Locale that the user has now this part is typically handled uh by third-party libraries like next Intel which are going to provide some convenient ways for you to either read from your local dictionaries that you create or it's going to be handled by your CMS for example if your data is coming in from a Content management system and that provides or supports different locales you'd have to create different versions of your content on the CMS and then fetch it depending on the Locale that the user is on to show them the correct content now let's just talk about the routing which is the first excuse me piece of the puzzle here so we're going to use these two packages the form address Intel local matcher and The Negotiator to actually understand the preferred language that the user has by reading the headers from the incoming request inside of a middleware so we're going to create a function called get Locale this is going to receive the request object this negotiator requires a plain object so if you're just mapping over the key value pairs inside of the headers of our request and mapping the values into a plane object so we can pass it to this new negotiator and then call this languages function to get the preferred languages of the user based on the request and then we're going to match the languages that are preferred by the user to the locales that we want to support so we're going to set some settings inside of our app either in the middleware or I'm going to show you how I prefer to do it inside a separate file to have this default Locale and the different locales or languages that we want to actually support we pass all of them to this match local function that we get I just realized that there is a typo here so this is as match Locale so you're getting this match function as match Locale from this package this is going to help us to pass the preferred languages of the user and the locals and default Locale that we provide to give us back a Locale that best matches what the user prefers now we're going to use this information inside of a middleware to actually redirect the user to what we think it's probably the language that they prefer so this is again the same thing that we have we have the packages here we have defined our locales we have this get Locale function again we're going to see this in the code so don't worry if you don't you can't follow it here but from a high level you're getting the Locale based on the request and then if you're just redirecting the user to a URL that implements that Locale that we got out of this get Locale function which was using these two packages to match the Locale that the user actually prefers and down here again we have a regular config that we're exporting from our middleware to telnex.js for which paths should this middleware actually run here we're just running it for all the paths and we're skipping our static underscore next JS folder with this negative look ahead regular expression now the second step to this after we having this middleware is to actually put all of our files layouts and Pages inside of a dynamic Lang or Locale folder inside of our app directory so therefore we have access to that specific Lang or Locale inside of our page components or layouts like so this is using regular Dynamic parameters in your react server components or pages which is this Dynamic parameters just like this link or ID or slug so the same way as we handle any other Dynamic route we'll just handle this Lang as well and we put everything inside of this Lang folder in our app including our root layout so all of them now have access to this slang and then we can use this combined with our local dictionaries which is just the mapping of keys and strings in different languages to show the correct content or the correct language to our users which brings us to the second piece of the puzzle or part of the process which is the actual localization now this is a pattern that we're using to implement this without using any third-party Library next js13 app router you can use third-party libraries the most popular one is next Intel it does not yet support server components in a stable version they do have a beta version Force localization in several components if you want to use it in client components you can and there is a stable version but in server components is still not there yet but I don't think it's even necessary at this point or for understanding how it works or the process we can just implement it yourself the way that we are explaining it here the main part of these libraries or the help of these libraries is in the localization part as I just mentioned it makes it easier for you to kind of map the dictionaries or the messages that you created in different languages to the actual components and elements in your pages now moving on here we are creating two dictionaries one for English so it's just a regular Json we are exporting from this file that has different keys or different Scopes these are going to be different elements on the page and there's going to be different strings so one for English in this case we're also having one for Dodge which is just translating whatever that we had there in the product scope and the cart to translate add to cart in Dutch now we're going to also have to create a function to actually load this dictionaries depending on the Locale that we send it to so this get dictionary function receives the Locale and then looks up to our dictionaries which is an object containing two keys that are dynamically importing these two Json data and then accessing these objects so this function is going to give us the dictionary on which we can just access the different keys that we want to show the strings of our elements again we're going to see this in action in the code so it makes more sense now we can use this get dictionary function inside of a page component we're going to get this locale from the dynamic part or parameter of the page send it to this get dictionary get our dictionary and then use that specific .product.cart to get that string depending on the language that the user prefers now for static generation because now all of our pages are living inside of this Lang Dynamic parameter you can use the generate static prompts this is a function index.13 or inside the app router that allows you to tell or instruct next.js what pages or paths you want to generate statically at build time you can just include all the languages or locales that you want to support so therefore you're going to build these pages statically so it's going to be an ear instant transition then actually users are changing locales so with that let's just jump into the code and implement this step by step so if you have a better understanding of how this works I have created a brand new Next JS application this is using typescript and Tailwind CSS and I'm not using the source directory and I'm going to explain step by step what I've added to the bare bone project that you get out of running the script so let's go inside of our app directory as you can see I've copied everything that comes out of the box into this lag folder this is a dynamic parameter we have created here so inside of it the outermost we have the layout this is our root layout let's just look at it first so inside of our root layout all I have done is to add this header we're going to look at the header in a second but we're also getting this page parameters and accessing the Lang property this is the dynamic part or the dynamic language or Locale to set this Lang attribute inside of our HTML okay so that's the only difference that this has compared to what you get out of the box now before diving into the header let me just actually go to the page component inside of our page component we are still receiving or we are again receiving this language Dynamic parameter we're using this get dictionary function that I'm going to show in a second pass that language to it to get our specific dictionary so that we can use that scope to actually pull in the title and description from our dictionary instead of hard coding this h1n subtitle so let's look at the get dictionary function first then I'm going to also show the dictionaries that I've created so inside of our app let me just close this off I've created this lib folder inside of it I have this dictionary file where I am ex defining the sketch dictionary function and this is literally returning the correct key from this dictionary object I have up top which is just importing these two Json files so going back to our app these Json files are actually living inside of this dictionaries folder where I have a Json file for every Locale that I want to support here I'm supporting English and Deutsche or German so I have two files and inside of them I have defined some Scopes so here I have navigation these are going to be my navigation links so I have a home home and about and I have a scope for my pages I have a home page on the home page I have a title and description so if I go back to the home page this is going to be the title and description and then I have an about page scope where I also have a title in its description which is going to be these two now similar to this I also have another Json file for the German version of the same keys so I have the navigation the home and about these are these two links I have a page scope where I have the home and about and again title and description Keys which is pointing to the German version or translation of those same strings so if I change into the German version we can see these two translations now going back to this file where I'm defining this get dictionaries function you can see I'm importing this Locale type from i18 config so if you go to our project root directory you can see this i18n config.ts this is a file where we can Define our internationalization settings in one place so we can use it and pull it different places that we need throughout our application I'm exporting this object that has my default Locale or the Locale that I want to support in my application I'm also exporting this type so I can use it to type anywhere that I'm actually using this Dynamic Lang property inside my pages or the locales now this pattern was inspired by an example from the next JS team so if you go to the documentation for internationalization if you scroll down to the end of the page you would see these two examples one is this minimal routing and translation and the other one is using the next Intel package as I mentioned this is still not stable for Server components but this minimal routing and translation is where I got the inspiration for our own application it's actually using the same patterns and packages there and as you can see they also do have this config file for i18n where they're defining these settings let's now have a look at our middleware this is similar to the example that I showed in the beginning where we're using these two packages the local matcher and The Negotiator to first get the Locale or the preferred language or Locale of the user based on the headers or the accept language header that comes on the request object and using that Locale inside of our middleware to determine whether or not we want to redirect the user to a specific Locale now that's all we're doing inside of our middleware function and down here in the bottom we are also using some negative look aheads to skip the static files in underscore next folder or favicons and static images so if you're not running this middleware for our static files it's just for our content pages that we are running it but you can use any other match or config that you want here to decide for what paths inside of your app you want to actually run this middleware now going back inside of our app folder you can see inside the Lang I also have this for this about page where it is about folder and a page component inside of it which is responsible for rendering the content of our about page and again similar to our home page if you're using this get dictionary function and we're receiving these page parameters because all of our pages and layouts now live inside of this lank folder they all now have access to this Lang parameter or dynamic prams object where you can just use it to pass it to our get dictionary to get the correct scope or the correct language and then depending on that axis whatever it is that we are trying to show on the page now going back to our app I just want to quickly touch on this component and the header that we have inside of it so going to our header component this is where we're actually showing these two links and these two buttons so let's quickly have a look at that and see what we're doing here so inside of our header there's just some navigation links for a navigation link just pay attention to that for going to the home page for example I'm sending them to forward slash and then I'm also including the locale and for the about link I'm also including the Locale so I'm sending them to the correct Locale every time and we're receiving this language property inside of our header component that comes from our page so if I go back to my root layout where I'm actually rendering this header so let's start from here let me just close that off so inside of our layout this is our outermost layout or root layout where we also get this prams object which has access to the link this is again the dynamic segment we are also passing that language down to this header component so the header component is also aware of the specific Locale so it can use it inside of our link components and also in this two buttons over there so going back to the header we're receiving this Lang props and then we're using that to select the correct dictionary again to show the correct text for our navigation links in this case but also have the Locale to forward the user to the correct page when they're actually clicking on these links then at the end we have this Locale Switcher which is importing this i18n object we are exporting from our config this is actually very defined the config of internationalization in our project to view exporting this i-18 and object and on it there was this locals property which is an array of different locales we're supporting so back in the suture we're just getting that object accessing different locales mapping over them for each one we're just rendering a link these are these two buttons that's going to just send the user to the correct link or the correct path with the Locale attached to it that comes out of this function the redirect path name function it takes in a Locale and spits out the path for which we want to actually link the user or re push the user to and just like that we were able to implement routing and localization in extras 13 Even though it wasn't supported in the app router out of the box we used the middleware and two packages to read the preferred Locale from the request headers and then to match it with different locales or to the best language that we do support on our application and we then used some local dictionaries to Define different Scopes and mappings for the actual localization of the string and the texts on our site if you have any questions hit me up in the comments if you learned something from this video please give it a like and I'll see you in the next one bye
Info
Channel: Hamed Bahram
Views: 53,715
Rating: undefined out of 5
Keywords:
Id: hA0Wp3KQYGU
Channel Id: undefined
Length: 22min 26sec (1346 seconds)
Published: Sat Jul 29 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.