Blog is now bilingual

Blog is now bilingual

Daily short news for you
  • For over a week now, I haven't posted anything, not because I have nothing to write about, but because I'm looking for ways to distribute more valuable content in this rapidly exploding AI era.

    As I shared earlier this year, the number of visitors to my blog is gradually declining. When I looked at the statistics, the number of users in the first six months of 2025 has dropped by 30% compared to the same period last year, and by 15% compared to the last six months of 2024. This indicates a reality that users are gradually leaving. What is the reason for this?

    I think the biggest reason is that user habits have changed. They primarily discover the blog through search engines, with Google being the largest. Almost half of the users return to the blog without going through the search step. This is a positive signal, but it's still not enough to increase the number of new users. Not to mention that now, Google has launched the AI Search Labs feature, which means AI displays summarized content when users search, further reducing the likelihood of users accessing the website. Interestingly, when Search Labs was introduced, English articles have taken over the rankings for the most accessed content.

    My articles are usually very long, sometimes reaching up to 2000 words. Writing such an article takes a lot of time. It's normal for many articles to go unread. I know and accept this because not everyone encounters the issues being discussed. For me, writing is a way to cultivate patience and thoughtfulness. Being able to help someone through my writing is a wonderful thing.

    Therefore, I am thinking of focusing on shorter and medium-length content to be able to write more. Long content will only be used when I want to write in detail or delve deeply into a particular topic. So, I am looking for ways to redesign the blog. Everyone, please stay tuned! 😄

    » Read more
  • CloudFlare has introduced the pay per crawl feature to charge for each time AI "crawls" data from your website. What does that mean 🤔?

    The purpose of SEO is to help search engines see the website. When users search for relevant content, your website appears in the search results. This is almost a win-win situation where Google helps more people discover your site, and in return, Google gets more users.

    Now, the game with AI Agents is different. AI Agents have to actively seek out information sources and conveniently "crawl" your data, then mix it up or do something with it that we can't even know. So this is almost a game that benefits only one side 🤔!?

    CloudFlare's move is to make AI Agents pay for each time they retrieve data from your website. If they don’t pay, then I won’t let them read my data. Something like that. Let’s wait a bit longer and see 🤓.

    » Read more
  • Continuing to update on the lawsuit between the Deno group and Oracle over the name JavaScript: It seems that Deno is at a disadvantage as the court has dismissed the Deno group's complaint. However, in August, they (Oracle) must be held accountable for each reason, acknowledging or denying the allegations presented by the Deno group in the lawsuit.

    JavaScript™ Trademark Update

    » Read more

The problem

A while ago, I consulted with the CTO about whether I should advertise the blog to make it more well-known. He hesitated for a moment and replied, "I don't think so. If possible, try expanding your user base to other countries." Before that, I thought I could spend money on advertising on some social media platforms to promote my blog to more people, thereby increasing traffic and prioritize displaying the website in search results. But after that answer, I suddenly remembered the plan I had before writing: "The blog must be in English."

But you know, I'm not good at English. I can understand some documents, but when it comes to speaking or writing... I had to postpone my plan and hope that someday someone would translate the articles for me - I thought. And then suddenly, one day, ChatGPT appeared, the most advanced natural language model. To put it simply, it can understand and write responses like a human, not just simple sentences assembled by a robot. If I ask it to translate my articles, the English writing style is likely to become smoother compared to using traditional tools like Google Translate.

Actually, I wanted to integrate the ChatGPT API into the admin page to have it directly translate Vietnamese articles into English. But I have been waiting for it to open the API in Vietnam for a long time. Unable to wait any longer, last week was a busy week as I just finished implementing the multilingual blog feature. Yes, I just integrated i18n for it.

The process

This is not the first time I have built a multilingual website. Before that, I participated in some projects, either building from scratch or contributing to maintenance and adding new features.

2coffee.dev was created quite a while ago and did not initially integrate i18n, so it took some time to research some i18n-supporting modules.

It was not difficult to find, @nuxtjs/i18n is a popular module for Nuxt.js, so there is no reason not to use it. Take a look at the documentation to see how to install, configure, and what it can do.

After researching, I started testing some cases to see how it works and if it meets my requirements. For example, how to switch languages, whether to support language switching by path (e.g., /vi for Vietnamese, /en for English, and / as the default for Vietnamese), how to configure different article URLs between the two languages (e.g., the current article URL is /bai-viet/ten-bai-viet but I want it to be /articles/article-title in English), and how to configure links on the website to point to the correct URL based on the language... there are many things to do.

And finally, the most important thing is the SEO configuration for a multilingual website. You have to do something to let search engines know that your website has more than one language, as well as the Vietnamese and English content of the same article to optimize search results. Luckily, before that, I had read about this issue, and Google also has a very detailed article on how to declare a multilingual website in Overview of international and multilingual site topics. Depending on the case, for example, I am declaring the sitemap address with Google Search Console so they can quickly update the information, but previously the sitemap was configured with only one language, so I need to add multilingual support.

Last week, I quickly implemented it. You see, the series of articles about Rust was temporarily paused to focus on completing the multilingual feature.

Challenges

Things never go as smooth as we want, and the integration of multilingual support is no exception. In fact, I almost had to give up because of an inexplicable bug at the last minute.

Since I did not integrate i18n from the beginning, I had to go back and find all the places where the language was displayed in the code, put them into language configuration files, translate them, and replace them with i18n module language display support.

The most time-consuming part was integrating paths in the <nuxt-link> tag, specifically the to prop. Normally, we use <nuxt-link to="/path"> to create links to the /path router. But as I mentioned, the article URLs between Vietnamese and English are different, so I had to use a new syntax: <nuxt-link :to="localePath({ name: 'bai-viet-id', params: { id: article.url } })">. The structure in localePath includes name as the route name and params to declare params in the URL for the new link. To make it easier to understand, take a look at my current folder structure:

Folder structure

Oh, then the name should just be bai-viet, why bai-viet-id? Yes, it took me quite some time to figure out how to declare a router that contains params, specifically _id here.

At this point, everything was almost done, and then I ran npm run generate to create the static website, but many errors appeared, and my efforts were to "fix" them. If I used SSR, many issues would be simpler, but I chose SSG to increase page loading speed, and SSG has a different way of building code compared to SSR, so I had to modify the code to be compatible with it.

Finally, when I thought everything was ready for deployment, upon checking again, I found that on the first load, my website had a brief layout glitch, even though it was just a small flicker, it was noticeable and annoying. Not to mention that this also caused search engines to rate it poorly in terms of performance.

If other errors leave clear notifications about the cause and location, with a layout issue, that's too far-fetched. I'm sure many people have been in this situation and desperate in trying to guess where the problem lies. As for me, I checked out each commit to see where the issue started. Quora, it appeared after the commit that added the i18n configuration.

Strange! What does i18n have to do with the layout? I thought the same, and I spent a lot of time searching for answers online, but it seems like no one has encountered this issue. I guess I need to create an issue about this problem on Github? Hmm... it would probably take a lot of time, not to mention I need to explain the project structure along with the issues I am facing to wait for someone else to answer. =='

I had to take matters into my own hands, so I debugged the differences between the two commits before and after adding the i18n module and discovered something. In the commit after adding the module, there was a CSS file that was loading slower, and it was also the CSS file for the broken component. Continuing to investigate why it was loading slower, I found that it was executed after a JavaScript file was downloaded, in other words, that JavaScript file contained code to download the CSS. So, that means the i18n module is trying to change the project structure it builds!?

I looked into the build configuration in the nuxt.config.js file, and there was an option enabled:

build: {
    …
    extractCSS: {
      ignoreOrder: true,  
    },  
}

This is an option to split CSS files into smaller files to increase loading speed. Perhaps the splitting of CSS conflicted with i18n, causing it to consider the other CSS file unimportant and can be loaded later, resulting in a brief layout glitch. I turned off that option, and... everything started working again. Luckily!

Next steps

The first step is writing code, and then it is a long journey.

First, I will ask ChatGPT to translate some articles that I feel it can handle into English, make some adjustments like formatting, images... because when I tried to translate an article, it didn't return the markdown format for me to copy. Some articles have code formatted in backticks (`), and they were broken when displayed in ChatGPT... so, after translation, many things still need to be edited before publishing a complete article.

Evaluate the effectiveness of SEO as well as fixing any future issues or problems that arise, because I don't have much experience in managing multilingual websites.

Although it's a translation, I will try to read through the translated articles and hope to learn more through this process!

Premium
Hello

The secret stack of Blog

As a developer, are you curious about the technology secrets or the technical debts of this blog? All secrets will be revealed in the article below. What are you waiting for, click now!

As a developer, are you curious about the technology secrets or the technical debts of this blog? All secrets will be revealed in the article below. What are you waiting for, click now!

View all

Subscribe to receive new article notifications

or
* The summary newsletter is sent every 1-2 weeks, cancel anytime.

Comments (1)

Leave a comment...
Avatar
Ẩn danh11 months ago

chào bạn có thể hướng dẫn rõ hơn về cách cài đặt đa ngôn ngữ cho blog không ạ?

Reply