<?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>Forem: Bramsurya Johannes Paulus</title>
    <description>The latest articles on Forem by Bramsurya Johannes Paulus (@bramsuryajp).</description>
    <link>https://forem.com/bramsuryajp</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%2F1601682%2Fa1812bc0-fee3-4198-8a54-87a5c22bb1ba.png</url>
      <title>Forem: Bramsurya Johannes Paulus</title>
      <link>https://forem.com/bramsuryajp</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/bramsuryajp"/>
    <language>en</language>
    <item>
      <title>I implement Next-Intl into my Portfolio (Next JS &amp; App Router)</title>
      <dc:creator>Bramsurya Johannes Paulus</dc:creator>
      <pubDate>Tue, 11 Jun 2024 06:12:18 +0000</pubDate>
      <link>https://forem.com/bramsuryajp/i-implement-next-intl-into-my-portfolio-next-js-app-router-fja</link>
      <guid>https://forem.com/bramsuryajp/i-implement-next-intl-into-my-portfolio-next-js-app-router-fja</guid>
      <description>&lt;p&gt;Before I dive into implementing the new feature (Next-Intl) I added to my portfolio, you might want to check it out first at &lt;a href="https://bram-portfolio-website.vercel.app/en"&gt;my portfolio&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Internationalization (often abbreviated as i18n) is an important aspect of web development, especially for websites that cater to a global audience. Here are some key features and benefits of using internationalization on your website:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Language Localization&lt;/strong&gt;: Internationalization allows your website to be translated into different languages. This makes your content accessible to users around the world, regardless of their native language.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved User Experience&lt;/strong&gt;: By providing content in a user’s native language and adhering to their cultural norms, you enhance their experience and engagement with your website.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SEO Benefits&lt;/strong&gt;: Search engines favor websites that cater to a global audience. By having your website content available in multiple languages, you can improve your search engine rankings.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Because I'm using Next JS as my tech to build my portfolio, I use the &lt;strong&gt;Next-Intl&lt;/strong&gt; so it will be compatible with my website. To implement &lt;strong&gt;Next-Intl&lt;/strong&gt; as I did in my portfolio you can follow this step(I will demonstrate this with my web code):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Add Next-Intl into your application&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   npm i next-intl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create this folder structure&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   ├── locales (1)
   │   ├── en.json
   │   └── ... // your others locales file (e.g. id.json)
   ├── next.config.js (2)
   ├── i18n.ts (3)
   ├── middleware.ts (4)
   └── app
       └── [locale]
           ├── layout.tsx (5)
           └── page.tsx (6)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can follow my folder structure example&lt;br&gt;
   &lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flinsuortgg06034trb0o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flinsuortgg06034trb0o.png" alt="Folder Structure Example" width="191" height="633"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Setup the files&lt;/strong&gt; &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add JSON files in your project based on locales(e.g. en.json, id.json)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;en.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  "Project": {
     "label": "My Projects"
  },
&lt;/code&gt;&lt;/pre&gt;



&lt;ol&gt;
&lt;li&gt;Add this code to your &lt;code&gt;next.config.js&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;next.config.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  // @ts-check
  const createNextIntlPlugin = require('next-intl/plugin')

  const withNextIntl = createNextIntlPlugin()

  /** @type {import('next').NextConfig} */

  const config = {}

  module.exports = withNextIntl(config)
&lt;/code&gt;&lt;/pre&gt;



&lt;ol&gt;
&lt;li&gt;Add this code to your &lt;code&gt;i18n.ts&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;i18n.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  import { notFound } from 'next/navigation'
  import { getRequestConfig } from 'next-intl/server'

  const locales = ['en', ...] // Add your other locales here

  export default getRequestConfig(async ({ locale }) =&amp;gt; { 
     // Validate that the incoming `locale` parameter is valid 
     if (!locales.includes(locale as any)) notFound()

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

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



&lt;ol&gt;
&lt;li&gt;Add this code to your &lt;code&gt;middleware.ts&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;middleware.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   import createMiddleware from 'next-intl/middleware'

   export default createMiddleware({
   // A list of all locales that are supported
   locales: ['en', ...], // Add your other locales

   // Used when no locale matches
   defaultLocale: 'en',
   })

   export const config = {
   // Match only internationalized pathnames
   matcher: ['/', '/(id|en)/:path*'],
   }
&lt;/code&gt;&lt;/pre&gt;



&lt;ol&gt;
&lt;li&gt;Add this code to your &lt;code&gt;app/[locale]/layout.tsx&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;app/[locale]/layout.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;```
import { NextIntlClientProvider } from 'next-intl'
import { getMessages } from 'next-intl/server'

type Props = {
   children: ReactNode
   params: { locale: string }
}

export default async function RootLayout({
  children,
  params: { locale },
}: Props) {
    const messages = await getMessages()
    return (
       &amp;lt;html lang={locale}&amp;gt;
         &amp;lt;body&amp;gt;
           &amp;lt;NextIntlClientProvider messages={messages}
               {children}
           &amp;lt;/NextIntlClientProvider&amp;gt;
         &amp;lt;/body&amp;gt;
       &amp;lt;/html&amp;gt;
    )
}
```
&lt;/code&gt;&lt;/pre&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Call your translation using &lt;code&gt;useTranslation&lt;/code&gt; in your page components or anywhere else!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;e.g. Projects.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useTranslations } from 'next-intl'

export default function Projects() {
   const t = useTranslations('Project')

   return (&amp;lt;p&amp;gt;{t('label')}&amp;lt;/p&amp;gt;)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can make a language toggler button to switch language as you wish, but before that you guys need to make a routing using &lt;strong&gt;Next-Intl&lt;/strong&gt; so follow this step: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;config.ts&lt;/code&gt; on your root folder and add this code&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;config.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   export const locales = ['en', 'id'] as const

   // Use the default: `always`
   export const localePrefix = undefined
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;navigation.ts&lt;/code&gt; on your root folder and add this code&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;navigation.ts&lt;/code&gt;&lt;br&gt;
&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, localePrefix } from './config'

export const { Link, redirect, usePathname, useRouter } =
   createSharedPathnamesNavigation({
      locales,
      localePrefix,
   })
```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;If you done two of the previous step you can make the language button toggler&lt;/p&gt;

&lt;p&gt;&lt;code&gt;LangToggler.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'use client'

import { useTransition } from 'react'
import { useRouter, usePathname } from '../navigation'
import { useLocale } from 'next-intl'

import inaIcon from '@/public/ina-icon.svg'
import enIcon from '@/public/en-icon.svg'
import Image from 'next/image'

export default function LangToggler() {
    const router = useRouter()
    const [isPending, startTransition] = useTransition()
    const pathname = usePathname()
    const locale = useLocale()

    const nextLocale = locale === 'en' ? 'id' : 'en'

    function onButtonClick() {
        startTransition(() =&amp;gt; {
             router.replace(pathname, { locale: nextLocale })
        })
    }

    return (
       &amp;lt;button
           disabled={isPending}
           onClick={onButtonClick}
       &amp;gt;
           &amp;lt;Image
              src={locale === 'en' ? inaIcon : enIcon}
              alt='language flag icon'
              className='w-4'
           /&amp;gt;
       &amp;lt;/button&amp;gt;
    )
}

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

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Voila, you have done adding Next-Intl to your application. This is an example of my portfolio website&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flb5jsogq4ud1x9drngmx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flb5jsogq4ud1x9drngmx.png" alt="My Web with English Language" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fodiln5v7dl69zrxyhnvu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fodiln5v7dl69zrxyhnvu.png" alt="My Web with Indonesian Language" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy coding guys, Thankyou!&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>frontend</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
