🙋♂️ I'm open for freelance offers.
💫If you don't need a freelancer, a small tip will still be appreciated, so I'll be able to create more repositories (or improve the existing ones) and spend some time to help the community!
The other way to support me, is to buy me some artworks, thank you!
IMPORTANT NOTE:
This is still a WIP (Work In Progress).
I recently changed all the complex server logic for pagination and tags, with the use of Zustand library, and moved it all to two components (pagination, and ListLayout)
While it's not optimal for SEO purposes, the goal of these changes is to find a solution for managing all the url in a better way (translated urls are very bad for SEO)
Also, I don't think that the impact of these first changes is really bad for SEO, because most users will use this repository and code for their personal dev blog.
So for now, blog page and tags logic is entirely managed on client side (also resulting in a faster UI for users). This also means less complex server side code and pages.
sitemap.xml and robots.txt are now handled perfectly. I made all the necessary changes, next step is to fix rss.
How can YOU help? You can help this project by making PR. I need help to optimize the performances on mobile
Introduction
In this post we will discuss the i18n implementation and how it changes compared to the original V.2.
For a better understanding of the basic functionalities, you will need to consult the other posts, or the original documentation
on timlrx github.
Using the repo? Let me know and I'll start a list if you want your own blog listed there.
If you find this project useful, please give it a ⭐ to show your support.
Motivation
The original model is amazing, and all major credits for it go to its creator @Timlrx. I was using V.1 of the i18n version, which was rather complicated to use and which it seems that the creator has unfortunately abandoned. So this is my participation and my donation to the community!
Also, I am currently redesigning my own website, which uses the router page, and part of the code for the internationalized blog of V.1.
I wanted to migrate to the app router, but for that, I first had to learn how to internationalize a site with the router app, so I took this repository as training.
I love the idea of helping other developers to quickly start sharing their precious knowledge with the whole world, making the internet better, whether in their native language, or in English 😌
I also designed a much more complete template for artists, content creators and developers, which I m'using for my own site and which is available here :
Normal version :
I18 version :
My own website based on this new template :
Changes:
New features
This repository will sometimes be updated with new features (not present in the original repository)
All this can sometimes seem obsessive regarding the UI and details, -maybe too neat or a little overkill- but I also use this repository as a play and learning space.
For now :
-
New "WebsiteEmbed" MDX component : Embed your demo templates from github with ease, and show them on your website! (Don't forget to update your Content Security Policy in the config files of your templates)
-
New "sidetoc" component : display automatically the table of contents of your posts in a dedicated sidebar.
-
Integration of email, theme, as well as a button to quickly copy the URL of the page you are on, with the kbar palette command.
The motivation for this is having explored other command palette libraries, with some offering nested elements for 'Actions'. Unfortunately this is not possible with kbar, but it gave me new ideas!
-
Multi-authors feature for "about" section: each author can have it's own about page available inside a dropdown menu on large screens, or displayed directly on small screens. If you want to turn it off and only use the "normal", classical about section, go to sitemetadata.js and set multiauthors to false. In any case, your main author now needs to have the field "default" set to true.
-
Featured section on home page for posts you want to pin to top : set featured to true (max two posts by default, can be modified in Featured.tsx file, in component folder) The program will pick the latest two posts with "featured : true." If no featured posts are available, this section will simply not be displayed!
-
Each tag now has its own pagination! If the number of posts is greater than the one you have defined (by default, set to 5) then a new page is automatically created for subsequent posts including the same tag.
-
Waline comment system now supported! It's probably the best open source comment system right now, with even i18n and many other great features! First, follow the official tutorial to set up the comments database and your vercel server. There's many options available, so take the time to read their documentation. Since it's Vue based, it's still compatible with Next.js, and I created a new comment component. You'll find it in "walinecomponents" folder. I also added a new css file, and you can modify the style here if needed. Once you have deployed your application for comments, modify the sitemetadata.js file. Set "iscomments" property to false, set "iswaline"
to true and set the url of your comments server accordingly in "walineServer". If your language is not supported by waline, make a PR to their repository or ask them kindly to add your own translation (provide it yourself first). This is what I did for supporting french, and this how we work in open source world!
-
Series for your posts is now supported, see the deployed demo!
Example of including this new feature :
title: Internationalization of V 2.0
series:
order: 4 // You must add a number for the actual order of your post in your series
title: "Blog Starter" // You must add the same title to all of your posts from the same series
date: '2023-11-17'
lastmod: '2023-11-17'
language: en
tags: ['next-js', 'tailwind', 'guide', 'features', 'i18n']
authors: ['default']
images: ['/static/images/twitter-card.png']
draft: false
summary: Presentation of the Starter Blog Tailwind Next-js v2.0, with addition and support for multiple languages.
-
Share component : you or your users can share your blog posts on Facebook, Twitter, Linkedin, WhatsApp, Threads or Telegram with ease! What's a 2024 modern blog without this possibility?
-
Smooth page transitions thanks to Framer Motion (see the template.tsx file in the app folder and take a look at the following next.js documentation
for file functionality template)
I strongly encourage you to experiment with framer-motion and its use within the new
router. I also added some Framer Motion flavor to the formspree contact modal, and to the ListLayoutWithTags.tsx component
Note : the template.tsx file is now removed, because there's performances issues with it. I'll try to implement animations handled in a better way. If you don't care about mobile performance and like this animation, you can stick with it, here's the code :
'use client'
import { motion } from 'framer-motion'
const variants = {
hidden: { opacity: 0, x: -50, y: 0 },
enter: { opacity: 1, x: 0, y: 0 },
}
export default function Template({ children }: { children: React.ReactNode }) {
return (
<motion.main
variants={variants}
initial="hidden"
animate="enter"
transition={{ type: 'linear' }}
>
{children}
</motion.main>
)
}
-
New MDX component: excellent audio player for mdx files (in case you make podcasts, or even music), thanks to react-h5-audio-player
-
Tailwind screen size indicator: a little help for development mode and responsive design (see TwSizeIndicator.tsx in /components/helper)
-
Formspree support for the mail icon, with a beautiful modal dialog. Formspree allows your users to contact you and send you messages directly from your site, with anti-spam protection. Simply create a free basic account, read the docs and get the key from your formspree account and then replace the key with your own here, in components/formspree/index.tsx :
/* Line 11*/
const [state, handleSubmit, reset] = useForm('xdojkndq')
IMPORTANT NOTE: you must replace the key in useform like this : useform('[your key]'). The provided key is
a test one of mine. You can use it to verify if the toast box is functional for example, but you must know
that I'll receive all your test messages. (You can still send me a friendly hello message!)
If you don't want to use Formspree, go to the siteMetadata.js file and set formspree to "false".
Libraries
For translations, the chosen library is not next-translate as in V.1 of GautierArcin, but the following libraries:
- i18next
- i18next-browser-languagedetector
- i18next-resources-to-backend
- React-i18next
Indeed, with the new version of next-js and the router app, it was easier for me to find information and tutorials to make everything work as expected. (I first tried with next-translate, but there are too many unresolved issues currently with this library and the features related to the new router)
Configuration
Within the app folder, all content has been moved to a new folder [locale]: this is the official way recommended by next.js. An i18n folder has also been added:
app
│
[locale]
│
├── i18n
│ │
│ ├──locales
│ │ │
│ │ ├── en
│ │ │ ├── about.json
│ │ │ │
│ │ │ ├── home.json
│ │ │ │
│ │ │ └── ...
│ │ └── fr
│ │ ├── about.json
│ │ │
│ │ ├── home.json
│ │ │
│ │ └── ...
│ │
│ │
│ ├── client.ts
│ ├── locales.js
│ ├── server.ts
│ └── settings.ts
│
└── ...
It is therefore in this i18n folder that the main logic for the internationalization of the application is located.
The "locales" subfolder contains the .json files where you will define your translations, the convention being to define one file per page of your site, with the name of the page concerned for the name of the json file.
There is also a "common" file: if you do not specify a "namespace" or ns (the name of the file without the json extension) in your pages or components, the translations will be taken from this file by default.
*Important: for each language there must be a corresponding file with the same name, for example an "about" file for "fr" and for "en", etc. As well as translation keys with the same name within
of each file.
Example :
In English in the "en" folder:
{
"title": "Projects",
"description": "Showcase your projects with a hero image (16 x 9)",
"learn": "Learn more",
"subtitle": "Here you will find information about my current projects",
"linkto": "Link to"
}
In French in the "fr" folder:
{
"title": "Projets",
"description": "Présentez vos projets avec une image (16 x 9)",
"learn": "En savoir plus",
"subtitle": "Ici vous trouverez des informations sur mes projets actuels.",
"linkto": "Lien vers"
}
This is the file where you will define the languages you want to use, as well as the default language:
const fallbackLng = 'en' // default la