<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Albert </title>
    <description>The latest articles on DEV Community by Albert  (@albertdugba).</description>
    <link>https://dev.to/albertdugba</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F23934%2Fbe6d13c0-f864-4b4a-95a5-05b2631f53ce.jpeg</url>
      <title>DEV Community: Albert </title>
      <link>https://dev.to/albertdugba</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/albertdugba"/>
    <language>en</language>
    <item>
      <title>Localization in Nextjs with App Router</title>
      <dc:creator>Albert </dc:creator>
      <pubDate>Tue, 30 Jul 2024 11:38:06 +0000</pubDate>
      <link>https://dev.to/albertdugba/localization-in-nextjs-with-app-router-4efd</link>
      <guid>https://dev.to/albertdugba/localization-in-nextjs-with-app-router-4efd</guid>
      <description>&lt;p&gt;Localization is a very important aspect of building an application, especially when you have users with different languages in a new target market. The goal of localization is to break down the communication barriers making content more accessible to everyone. It's not something we think about but it's very important.&lt;br&gt;
In this article, we will be looking at how to set up localization in nextjs application with the app router.&lt;/p&gt;

&lt;h3&gt;
  
  
  What we will cover in this post
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create a new nextjs application&lt;/li&gt;
&lt;li&gt;Install the 118next package&lt;/li&gt;
&lt;li&gt;Write translation files&lt;/li&gt;
&lt;li&gt;Configure the &lt;code&gt;next-intl&lt;/code&gt; package&lt;/li&gt;
&lt;li&gt;Tailor our internationalization library according to our needs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the purposes of the post, we will be building out a basic e-commerce application. To see a live working version of this blog post, check out the &lt;a href="https://localization-in-nextjs-sample-app.vercel.app/en" rel="noopener noreferrer"&gt;demo-app&lt;/a&gt; over here. You can also access to the &lt;a href="https://github.com/albertdugba/localization-in-nextjs-sample-app" rel="noopener noreferrer"&gt;complete source code on github&lt;/a&gt; here too.&lt;/p&gt;

&lt;h4&gt;
  
  
  Create a new nextjs application
&lt;/h4&gt;

&lt;p&gt;I prefer to use &lt;code&gt;pnpm&lt;/code&gt; but you can any package manager of your choice.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

pnpm create-next-app@latest


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Install the &lt;code&gt;next-intl&lt;/code&gt; library
&lt;/h4&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

pnpm install next-intl


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Create Messages file
&lt;/h4&gt;

&lt;p&gt;After the installation, the first step is to create a messages folder at the root of your application&lt;br&gt;
You can save the messages locally or fetch them from a remote source depending on your workflow.&lt;/p&gt;

&lt;p&gt;At the root of your project, create a messages folder where you can create JSON files for each locale like below.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

{
  "Index": {
    "title": "Hello world!"
  }
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Configure Plugin
&lt;/h4&gt;

&lt;p&gt;The next step is to configure the &lt;code&gt;createNextIntlPlugin&lt;/code&gt; plugin from the &lt;code&gt;next-intl&lt;/code&gt; package in your &lt;code&gt;next.config&lt;/code&gt; files. This plugin will provide the i18n configuration to the server components as follows:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import createNextIntlPlugin from "next-intl/plugin";

const withNextIntl = createNextIntlPlugin();

/** @type {import('next').NextConfig} */
const nextConfig = {};

export default withNextIntl(nextConfig);


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Create &lt;code&gt;i18n.ts&lt;/code&gt; file to setup the configuration
&lt;/h4&gt;

&lt;p&gt;After this, create a &lt;code&gt;i18n.ts&lt;/code&gt; file. This is to create a request-scoped configuration that can be used to provide messages based on the user's locale in the server components&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import { notFound } from "next/navigation";
import { getRequestConfig } from "next-intl/server";

const locales = ["en", "de"];

export default getRequestConfig(async ({ locale }) =&amp;gt; {
  if (!locales.includes(locale)) notFound();

  return {
    messages: (await import(`../messages/${locale}.json`)).default,
  };
});



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Create a middleware to handle requests
&lt;/h4&gt;

&lt;p&gt;Middleware is used to determine the locale for each request and handle redirects accordingly. In this step, you'll list all the supported locales for your application and match them with the pathnames. You can also set a default locale so that incoming requests automatically default to it if no specific locale is specified.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import createMiddleware from 'next-intl/middleware';

export default createMiddleware({
  locales: ['en', 'de'],
  defaultLocale: 'en'
});

export const config = {
  matcher: ['/', '/(de|en)/:path*']
};


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This code sets up middleware that supports English and German, with English as the default locale. It will match the specified paths and handle locale-based routing for your application.&lt;/p&gt;

&lt;h4&gt;
  
  
  Create a locale in the &lt;code&gt;app/[locale]/layout.tsx&lt;/code&gt; file
&lt;/h4&gt;

&lt;p&gt;Since we have already set up the middleware with the respective locales, we can retrieve the matched locale from the params and use it to configure the page language in the layout.tsx file. We will then pass the messages to the NextIntlClientProvider.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import { AbstractIntlMessages, NextIntlClientProvider } from "next-intl";
import { getMessages } from "next-intl/server";
import { Header } from "./Header";
import ProductCard from "./Card";
import { HeroSection } from "./HeroSection";

export default async function LocaleLayout({
  children,
  params: { locale },
}: {
  children: React.ReactNode;
  params: { locale: string };
}) {
  const messages = await getMessages();

  return (
    &amp;lt;html lang={locale}&amp;gt;
      &amp;lt;body&amp;gt;
        &amp;lt;NextIntlClientProvider
          messages={JSON.stringify(messages) as unknown as AbstractIntlMessages}
        &amp;gt;
          &amp;lt;div className='max-w-6xl mx-auto p-12'&amp;gt;
            &amp;lt;Header /&amp;gt;
          &amp;lt;/div&amp;gt;
          &amp;lt;HeroSection /&amp;gt;
          &amp;lt;main className='max-w-6xl mx-auto p-12'&amp;gt;{children}&amp;lt;/main&amp;gt;
        &amp;lt;/NextIntlClientProvider&amp;gt;
      &amp;lt;/body&amp;gt;
    &amp;lt;/html&amp;gt;
  );
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Your project structure should look like this&lt;/p&gt;

&lt;p&gt;├── public/&lt;br&gt;
├── messages/&lt;br&gt;
│   ├── en.json&lt;br&gt;
│   └── de.json&lt;br&gt;
├── src/&lt;br&gt;
│   ├── config.ts&lt;br&gt;
│   ├── i18n.ts&lt;br&gt;
│   ├── middleware.ts&lt;br&gt;
│   ├── navigation.ts&lt;br&gt;
│   ├── app/&lt;br&gt;
│   │   └── [locale]/&lt;br&gt;
│   │       ├── layout.tsx&lt;br&gt;
│   │       ├── page.tsx&lt;br&gt;
│   │       └── components/&lt;br&gt;
│   └── pages/&lt;br&gt;
│       ├── index.js&lt;br&gt;
│       └── about.js&lt;br&gt;
├── package.json&lt;br&gt;
└── README.md&lt;/p&gt;

&lt;h2&gt;
  
  
  Rendering i18n messages with the &lt;code&gt;useTranslations&lt;/code&gt; hook
&lt;/h2&gt;

&lt;p&gt;It is now time to render the 118next messages based on the user settings in the UI. &lt;code&gt;next-intl&lt;/code&gt; provides a &lt;code&gt;useTranslations&lt;/code&gt; hook used to render the messages. The hook takes in a &lt;code&gt;namespace&lt;/code&gt; or a &lt;code&gt;key&lt;/code&gt; based on the structure of your &lt;code&gt;"language.json"&lt;/code&gt; file.&lt;br&gt;
To illustrate let's integrate the translation capabilities into our product app starting from the hero HeroSection. In our application we have&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

 "Hero": {
    "title": "Der beste Online-Shop der Welt für Laptops und Macbooks",
    "ctaButton": "Jetzt kaufen"
  },


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import { useTranslations } from "next-intl";

export const HeroSection = () =&amp;gt; {
  const t = useTranslations("Hero");
  return (
    &amp;lt;section className='Hero-banner flex items-center justify-center lg:p-8 p-4'&amp;gt;
      &amp;lt;div className='flex flex-col'&amp;gt;
        &amp;lt;h1 className='lg:text-3xl text-lg text-white text-center'&amp;gt;
          {t("title")}
        &amp;lt;/h1&amp;gt;
        &amp;lt;div className='flex items-center justify-center'&amp;gt;
          &amp;lt;button className='bg-black text-white px-6 py-2 w-fit my-8'&amp;gt;
            Shop Now
          &amp;lt;/button&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/section&amp;gt;
  );
};


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;It uses the &lt;code&gt;key&lt;/code&gt; to retrieve the corresponding messages.&lt;br&gt;
Now when you check your browser on &lt;code&gt;http://localhost:3000/en&lt;/code&gt;, it shows the English version of the translations while &lt;code&gt;http://localhost:3000/de&lt;/code&gt; shows the German version like below&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdsdifoazf%2Fimage%2Fupload%2Fv1722339150%2Flang_vEL45vGM_apzabu.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdsdifoazf%2Fimage%2Fupload%2Fv1722339150%2Flang_vEL45vGM_apzabu.gif" alt="(Translation Example)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Interpolation of dynamic values
&lt;/h2&gt;

&lt;p&gt;This is a technique that can be used to insert dynamic values into a prefixed text.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

"message": "Hello {name}!"


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We can replace the &lt;code&gt;{name}&lt;/code&gt; with a dynamic value&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

t('message', {name: 'Albert'});


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;resulting in&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

"Hello Albert"


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;next-intl&lt;/code&gt; also supports formatting rich texts with custom tags&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

{
  "message": "Please refer to &amp;lt;guidelines&amp;gt;the guidelines&amp;lt;/guidelines&amp;gt;."
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

t.rich('message', {
  guidelines: (chunks) =&amp;gt; &amp;lt;a href="/guidelines"&amp;gt;{chunks}&amp;lt;/a&amp;gt;
});


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;To render an array of messages, we can map over the keys to the corresponding messages like in our little e-commerce application&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

    "data": {
      "product1": {
        "title": "Macbook Pro",
        "price": 1200,
        "image": "/products/macbook-pro.jpg",
        "description": "Work on anything, anywhere with the incredibly light and speedy Macbook Air 2020. The M1 chip is a game-changer. It's 3.5x faster than the previous Macbook Air, and packs in 8 CPU and 7 GPU cores so you can take on video-editing and gaming. Plus, it's incredibly power-efficient. The M1 lets you browse for up to 15 hours, or watch Apple TV for around 18 - that's a full flight from London to Sydney!"
      },
     ...others
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The recommended approach to render the product cards is to map over the keys like this&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import {useTranslations, useMessages} from 'next-intl';

function ProductList() {
  const t = useTranslations('Products');

  const messages = useMessages();
  const keys = Object.keys(messages.Products.data);

  return (
    &amp;lt;ul&amp;gt;
      {keys.map((key) =&amp;gt; (
        &amp;lt;li key={key}&amp;gt;
          &amp;lt;h2&amp;gt;{t(`${key}.title`)}&amp;lt;/h2&amp;gt;
          &amp;lt;p&amp;gt;{t(`${key}.description`)}&amp;lt;/p&amp;gt;
        &amp;lt;/li&amp;gt;
      ))}
    &amp;lt;/ul&amp;gt;
  );
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We need to render each product card so we can use &lt;code&gt;Object.values&lt;/code&gt; like this&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

export default function Index() {
  const t = useTranslations("Product");
  const messages: any = useMessages();

  const products = Object.values(messages.Product.data) as unknown as Product[];

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;div className='mt-4'&amp;gt;
        &amp;lt;div className='mb-4'&amp;gt;
          &amp;lt;h1&amp;gt;{t("title")}&amp;lt;/h1&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;ul className='grid lg:grid-cols-3 grid-cols-1 gap-9'&amp;gt;
          {products.map((product: Product, i: number) =&amp;gt; (
            &amp;lt;li key={i}&amp;gt;
              &amp;lt;ProductCard
                buttonText={t("productCardMeta.buttonText")}
                key={i}
                product={product}
              /&amp;gt;
            &amp;lt;/li&amp;gt;
          ))}
        &amp;lt;/ul&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This should work as expected&lt;/p&gt;

&lt;h3&gt;
  
  
  Formatting Numbers
&lt;/h3&gt;

&lt;p&gt;You can also format a number within a message&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

{
  "price": "This product costs {price, number, currency}"
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

t(
  'price',
  {price: 32000.99},
  {
    number: {
      currency: {
        style: 'currency',
        currency: 'EUR'
      }
    }
  }
);


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Implementing language switching in Next.js App Router using next-intl
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;next-intl&lt;/code&gt; simplifies language switching in Next.js by automatically handling locale information within standard navigation APIs.&lt;br&gt;
By employing shared pathnames, you can directly map Next.js routes to user-requested URLs without additional complexity.&lt;br&gt;
With this configuration, you gain access to routing components and methods like Link and usePathname, enabling intuitive navigation within your Next.js project.&lt;br&gt;
Create a &lt;code&gt;navigation.ts&lt;/code&gt; in your &lt;code&gt;src&lt;/code&gt; folder and add the following:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import { createSharedPathnamesNavigation } from "next-intl/navigation";
import { locales } from "./config";

export const { Link, redirect, usePathname, useRouter } =
  createSharedPathnamesNavigation({ locales });



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;To implement a language switch feature in your Navbar or any desired page, you can attach the pathname to the href property along with a locale. Here’s an example of a &lt;code&gt;Header.tsx&lt;/code&gt; component:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;p&gt;"use client";&lt;br&gt;
import { useEffect, useState } from "react";&lt;br&gt;
import Link from "next/link";&lt;br&gt;
import Image from "next/image";&lt;br&gt;
import { usePathname } from "next/navigation";&lt;/p&gt;

&lt;p&gt;import { locales } from "~/config";&lt;br&gt;
import { LocalLink } from "./LocalLink";&lt;/p&gt;

&lt;p&gt;type LocaleItem = "en" | "de";&lt;/p&gt;

&lt;p&gt;const NAV_LINKS = ["Shop", "Cart"];&lt;/p&gt;

&lt;p&gt;export const Header = () =&amp;gt; {&lt;br&gt;
  const [selected, setSelected] = useState&amp;lt;LocaleItem&amp;gt;();&lt;br&gt;
  const pathname = usePathname();&lt;/p&gt;

&lt;p&gt;const localePath = pathname.split("/")[1];&lt;/p&gt;

&lt;p&gt;const handleChangeLocale = (item: LocaleItem) =&amp;gt; {&lt;br&gt;
    setSelected(item);&lt;br&gt;
  };&lt;/p&gt;

&lt;p&gt;useEffect(() =&amp;gt; {&lt;br&gt;
    setSelected(localePath as LocaleItem);&lt;br&gt;
  }, [localePath]);&lt;/p&gt;

&lt;p&gt;return (&lt;br&gt;
    &amp;lt;header className='flex items-center justify-between'&amp;gt;&lt;br&gt;
      &amp;lt;h1&amp;gt;Tech Shop&amp;lt;/h1&amp;gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  &amp;amp;lt;ul className='flex items-center gap-2'&amp;amp;gt;
    {NAV_LINKS.map((nav) =&amp;amp;gt; (
      &amp;amp;lt;li key={nav}&amp;amp;gt;
        &amp;amp;lt;Link href='#'&amp;amp;gt;{nav}&amp;amp;lt;/Link&amp;amp;gt;
      &amp;amp;lt;/li&amp;amp;gt;
    ))}
  &amp;amp;lt;/ul&amp;amp;gt;
  &amp;amp;lt;div className='relative flex items-center justify-center rounded-full'&amp;amp;gt;
    &amp;amp;lt;ul className='bg-white flex'&amp;amp;gt;
      {locales.map((locale, i) =&amp;amp;gt; (
        &amp;amp;lt;li
          key={i}
          onClick={() =&amp;amp;gt; handleChangeLocale(locale as LocaleItem)}
          className={`border-l border-t border-b last:border-r ${
            selected === locale ? "bg-gray-100" : ""
          }`}
        &amp;amp;gt;
          &amp;amp;lt;LocalLink
            locale={locale}
            className={`flex p-4 items-center gap-2`}
          &amp;amp;gt;
            &amp;amp;lt;Image
              src={`/icons/${locale}.svg`}
              alt=''
              height={20}
              width={20}
              className='rounded-full'
            /&amp;amp;gt;
            &amp;amp;lt;h4 className='uppercase text-sm'&amp;amp;gt;{locale}&amp;amp;lt;/h4&amp;amp;gt;
          &amp;amp;lt;/LocalLink&amp;amp;gt;
        &amp;amp;lt;/li&amp;amp;gt;
      ))}
    &amp;amp;lt;/ul&amp;amp;gt;
  &amp;amp;lt;/div&amp;amp;gt;
&amp;amp;lt;/header&amp;amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;);&lt;br&gt;
};&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Wrapping up&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;I hope this post was helpful to you. You can find the &lt;a href="https://github.com/albertdugba/localization-in-nextjs-sample-app" rel="noopener noreferrer"&gt;complete source code on github&lt;/a&gt; and the &lt;a href="https://localization-in-nextjs-sample-app.vercel.app/en" rel="noopener noreferrer"&gt;demo-app&lt;/a&gt; over here.&lt;br&gt;
You can read more on the &lt;a href="https://next-intl-docs.vercel.app/" rel="noopener noreferrer"&gt;official documentation site&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The full guide is published here on my &lt;a href="https://albertdugba.dev/blog/localization-in-nextjs" rel="noopener noreferrer"&gt;personal website&lt;/a&gt; 😉&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://next-intl-docs.vercel.app/" rel="noopener noreferrer"&gt;next-intl documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>i18next</category>
      <category>localization</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Socketio chat app with node and mysql</title>
      <dc:creator>Albert </dc:creator>
      <pubDate>Mon, 10 Aug 2020 12:05:00 +0000</pubDate>
      <link>https://dev.to/albertdugba/how-to-get-data-from-a-database-47h1</link>
      <guid>https://dev.to/albertdugba/how-to-get-data-from-a-database-47h1</guid>
      <description>&lt;p&gt;Hello guys, am building a chat app with node and socket.io . I have persisted the data to mysql database successfully. Now, my next task is to retrieve the data and display on the web page so when it refreshes, it doesn't go away. This is what  I have done so far.&lt;br&gt;
Below is my code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;server.js
const db = mysql.createConnection({
  host: "localhost",
  user: "root",
  password: "",
  database: "live_chat",
});
app.use("/chat_messages", (req, res) =&amp;gt; {
  db.query("SELECT * FROM chat_messages", (error, messages) =&amp;gt; {
    res.end();
  });
});
app.use(express.static(path.join(__dirname, "public")));
const botName = "Admin✅";
io.on("connection", socket =&amp;gt; {
  socket.on("joinRoom", ({ username, room }) =&amp;gt; {
    const user = userJoin(socket.id, username, room);
    db.query("INSERT INTO users (username) VALUES (' " + username + " ')");
    socket.join(user.room);
    socket.emit(
      "message",
      formatMessage(
        botName,
        `${username} you're welcome to laronshalley customer support`
      )
    );
    // broadcast a message when a user connects
    socket.broadcast
      .to(user.room)
      .emit(
        "message",
        formatMessage(
          botName,
          ` ${user.username} has connected to the live chat`
        )
      );
    // get room users
    // io.to(user.room).emit("rootUsers", {
    //   room: user.room,
    //   users: getRoomUsers(room),
    // });
  });
  // listen for events from the client
  socket.on("chatMessage", msg =&amp;gt; {
    const user = getCurrentUser(socket.id);
    io.to(user.room).emit("message", formatMessage(user.username, msg));
    db.query("INSERT INTO chat_messages (messages) VALUES (' " + msg + " ')");
  });
  // disconnects when a user closes the tab
  socket.on("disconnect", () =&amp;gt; {
    const user = userLeave(socket.id);
    if (user) {
      io.to(user.room).emit(
        "message",
        formatMessage(botName, `oops ${user.username} is disconnected`)
      );
    }
    // // get room users
    // io.to(user.room).emit("rootUsers", {
    //   room: user.room,
    //   users: getRoomUsers(room),
    // });
  });
});
const PORT = 5000 || process.env.PORT;
http.listen(PORT, () =&amp;gt; console.log("server is listening on port 5000"));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;frontend file
chat.js


const socket = io();
const serverUrl = "http:localhost:5000/chat_messages";
// get username and room from the url
const { username, room } = Qs.parse(location.search, {
  ignoreQueryPrefix: true,
});
// select room
socket.emit("joinRoom", { username, room });
// socket.on("roomUsers", ({ room, users }) =&amp;gt; {
//   outputRoomName(room);
//   outputRoomUsers(users);
// });
fetch(serverUrl)
  .then(response =&amp;gt; response.json())
  .then(data =&amp;gt; console.log(JSON.parse(data)))
  .catch(error =&amp;gt; console.log("Oops, something went wrong", error));
socket.on("message", msg =&amp;gt; {
  outputMessage(msg);
  // scroll
  chatMessages.scrollTop = chatMessages.scrollHeight;
});
chatForm.addEventListener("submit", event =&amp;gt; {
  event.preventDefault();
  const msg = event.target.elements.msg.value;
  // send data to the server
  socket.emit("chatMessage", msg);
  // clear form field
  event.target.elements.msg.value = "";
  event.target.elements.msg.focus();
});
const outputMessage = message =&amp;gt; {
  const div = document.createElement("div");
  div.classList.add("message");
  div.innerHTML = ` &amp;lt;p class="meta"&amp;gt;${message.username} &amp;lt;span&amp;gt;${message.time}&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;
  &amp;lt;p class="text"&amp;gt;
   ${message.text}
  &amp;lt;/p&amp;gt;`;
  document.querySelector(".chat__messages").appendChild(div);
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>node</category>
      <category>socketio</category>
      <category>mysql</category>
    </item>
    <item>
      <title>High Order Components (React)</title>
      <dc:creator>Albert </dc:creator>
      <pubDate>Sun, 05 Apr 2020 20:21:00 +0000</pubDate>
      <link>https://dev.to/albertdugba/high-order-components-4g4h</link>
      <guid>https://dev.to/albertdugba/high-order-components-4g4h</guid>
      <description>&lt;p&gt;When will be it be useful to use a high order components in react?&lt;/p&gt;

</description>
      <category>react</category>
      <category>help</category>
    </item>
    <item>
      <title>Flutter and Me</title>
      <dc:creator>Albert </dc:creator>
      <pubDate>Fri, 01 Nov 2019 08:43:37 +0000</pubDate>
      <link>https://dev.to/albertdugba/flutter-15j8</link>
      <guid>https://dev.to/albertdugba/flutter-15j8</guid>
      <description>&lt;p&gt;Hello devs ...So I applied to some marketing agency in my locality as a front end developer with specialization in react. I was called for an interview and then I was told they're currently need someone with mobile experience specifically flutter to work on their upcoming apps. &lt;/p&gt;

&lt;p&gt;My interviewer told me he was very much impressed with github repo page but he would like me to join them but will learn flutter since that was going to be their main stack for mobile apps.  I had to start learning right away and I could tell i  was making progress with it. Fast forward to three weeks of my stay , he asked me whether I could build a lock screen . The purpose of this is to display custom ads on them to customers. I told them  I could do it but I will take some time. I know somehow I could do it but  I just don't know how to go about this, to the execution. &lt;/p&gt;

&lt;p&gt;I feel like a fraud and sooner or later I will tagged as incompetent to serve as a developer in their company. &lt;/p&gt;

&lt;p&gt;Note: this happens to be my first developer role as I have never had any professional experience before and there is no other developer to look up to. It's all by myself.&lt;/p&gt;

&lt;p&gt;Please I need some advice. What should I do?&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dev</category>
      <category>android</category>
      <category>ios</category>
    </item>
    <item>
      <title>Redux or Context API?</title>
      <dc:creator>Albert </dc:creator>
      <pubDate>Mon, 24 Jun 2019 19:31:12 +0000</pubDate>
      <link>https://dev.to/albertdugba/redux-or-context-api-4e2a</link>
      <guid>https://dev.to/albertdugba/redux-or-context-api-4e2a</guid>
      <description>&lt;p&gt;Please is advisable to still redux even if you know the context API?&lt;/p&gt;

</description>
      <category>react</category>
      <category>devdiscuss</category>
      <category>javascript</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Logic &amp; Problem Solving</title>
      <dc:creator>Albert </dc:creator>
      <pubDate>Tue, 11 Jun 2019 06:56:53 +0000</pubDate>
      <link>https://dev.to/albertdugba/logic-problem-solving-gah</link>
      <guid>https://dev.to/albertdugba/logic-problem-solving-gah</guid>
      <description>&lt;p&gt;What are some of the tips and tricks you for logic and problem solving in programming as a beginner? How do you put pieces together to create one project without necessary going back to a YouTube or a udemy tutorials? What should you know?&lt;/p&gt;

</description>
      <category>codenewbie</category>
      <category>devdiscuss</category>
      <category>javascript</category>
    </item>
    <item>
      <title>MacBook pro upgrade</title>
      <dc:creator>Albert </dc:creator>
      <pubDate>Sat, 26 Jan 2019 23:20:47 +0000</pubDate>
      <link>https://dev.to/albertdugba/macbook-pro-upgrade-11ec</link>
      <guid>https://dev.to/albertdugba/macbook-pro-upgrade-11ec</guid>
      <description>&lt;p&gt;So I got a MacBook pro with 8GB of RAM  and a storage of 128GB for sometime now but am running out of space and am thinking of upgrading to 512GB. Is this a good idea?. Will it be less performant?&lt;/p&gt;

</description>
    </item>
    <item>
      <title>The difference between HTTPS and HTTP</title>
      <dc:creator>Albert </dc:creator>
      <pubDate>Sat, 25 Aug 2018 08:55:24 +0000</pubDate>
      <link>https://dev.to/albertdugba/the-difference-between-https-and-http-4nha</link>
      <guid>https://dev.to/albertdugba/the-difference-between-https-and-http-4nha</guid>
      <description>&lt;p&gt;&lt;em&gt;What is the difference between http and https?&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;Some of you may be aware of this differencde, but it is &lt;br&gt;
worth sharing for many that are not.&lt;/p&gt;

&lt;p&gt;The main difference between http:// and https:// is all about keeping you secure. &lt;/p&gt;

&lt;p&gt;HTTP stands  for Hyper Text Transfer Protocol.&lt;br&gt;&lt;br&gt;
The S (big  surprise)  stands for "Secure". If you visit a Website or web page, and look at the address in the web browser, it is likely begin with the following: http:///. &lt;/p&gt;

&lt;p&gt;This means that the website is talking to your browser using &lt;br&gt;
the regular unsecured language. In other words, it is possible for someone to  "eavesdrop" on your computer's conversation with  the Website. If you fill out a form on the website, someone might see the information you send to that site. &lt;/p&gt;

&lt;p&gt;This is why you never ever enter your credit card number in an &lt;br&gt;
Http website! But if the web address begins with https://, that means your computer is talking to the website in  a &lt;br&gt;
Secure code that no one can eavesdrop on.  &lt;/p&gt;

&lt;p&gt;Now, you understand why this is so important, right?  &lt;/p&gt;

&lt;p&gt;If a website ever asks you to enter your Credit/Debit card &lt;br&gt;
Information, you should automatically look to see if the web &lt;br&gt;
address begins with https://. &lt;/p&gt;

&lt;p&gt;If  it doesn't, you should NEVER enter sensitive Information such as a credit/debit card number. &lt;/p&gt;

&lt;p&gt;While checking the name of any website, first look for the domain extension (.com or .org, .co.in, .net  etc). The name just before this is the domain name of the website. Eg, in the above example, &lt;a href="http://amazon.diwali-festivals.com" rel="noopener noreferrer"&gt;http://amazon.diwali-festivals.com&lt;/a&gt;, the word before .com is "diwali-festivals" (and NOT "amazon"). So, this webpage does not belong to amazon.com but belongs to "diwali-festivals.com", which we all haven't heard of before.&lt;br&gt;
You can similarly check for bank frauds.&lt;br&gt;
Before your ebanking logins, make sure that the name just before ".com" is the name of your bank. "Something.icicibank.com" belongs to icici; but, icicibank.some1else.com belongs to "some1else.&lt;/p&gt;

</description>
      <category>https</category>
      <category>http</category>
    </item>
    <item>
      <title>What are the dos and dont of building a startup as a developer?</title>
      <dc:creator>Albert </dc:creator>
      <pubDate>Sat, 04 Aug 2018 17:09:02 +0000</pubDate>
      <link>https://dev.to/albertdugba/founding-a-startup-as-a-developer--1ckd</link>
      <guid>https://dev.to/albertdugba/founding-a-startup-as-a-developer--1ckd</guid>
      <description></description>
      <category>devdiscuss</category>
      <category>startup</category>
    </item>
    <item>
      <title>Go or Python and why?</title>
      <dc:creator>Albert </dc:creator>
      <pubDate>Fri, 18 May 2018 19:11:45 +0000</pubDate>
      <link>https://dev.to/albertdugba/go-or-python-and-why-58ob</link>
      <guid>https://dev.to/albertdugba/go-or-python-and-why-58ob</guid>
      <description>&lt;p&gt;So a friend of mine was considering either learning python òr go. What would be your advice to him?&lt;/p&gt;

</description>
      <category>go</category>
      <category>python</category>
      <category>devdiscuss</category>
    </item>
    <item>
      <title>Is Ruby lang dying?</title>
      <dc:creator>Albert </dc:creator>
      <pubDate>Sat, 24 Mar 2018 22:45:58 +0000</pubDate>
      <link>https://dev.to/albertdugba/ruby-lang--2k79</link>
      <guid>https://dev.to/albertdugba/ruby-lang--2k79</guid>
      <description>&lt;p&gt;Is ruby dying?&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>devdiscuss</category>
    </item>
    <item>
      <title>Business in tech</title>
      <dc:creator>Albert </dc:creator>
      <pubDate>Mon, 15 Jan 2018 09:55:24 +0000</pubDate>
      <link>https://dev.to/albertdugba/business-in-tech-1c8f</link>
      <guid>https://dev.to/albertdugba/business-in-tech-1c8f</guid>
      <description>&lt;p&gt;Aside the technical skills of a developer, what other skills are important especially for someone trying to build a start-up in this age?&lt;br&gt;
All submissions are welcome. Thanks &lt;/p&gt;

</description>
      <category>startup</category>
      <category>business</category>
      <category>development</category>
    </item>
  </channel>
</rss>
