Databases & Backend

NestJS i18n for Vietnamese: Setup Guide

Most tutorials stop at basic i18n. Building for Vietnamese users? You need more than just a language switch – you need nuance and a setup that doesn't fight you.

Screenshot of Vietnamese translation files for NestJS i18n setup.

Key Takeaways

  • Proper Vietnamese i18n requires handling tone marks and polite phrasing, not just string replacement.
  • The `nestjs-i18n` library simplifies Unicode handling and translation management in NestJS.
  • Auto-detection via the `Accept-Language` header allows for smoothly language serving based on browser settings.

Look, another week, another “game-changing” tutorial about adding a language to your app. Usually, it’s English and Spanish, right? Groundbreaking. But if you’re actually trying to talk to folks who speak Vietnamese, suddenly the complexity ramps up. Tone marks, polite phrasing, the whole nine yards. This isn’t just about swapping out words; it’s about respect, and frankly, avoiding looking like a clueless Silicon Valley bro who thinks “international” means “Europe plus Mexico.”

And if you’re stuck in the NestJS ecosystem, you’ve probably seen the same old advice. Well, guess what? It’s possible. It’s not exactly rocket science, but it does require a bit more than just npm install. This is about getting your API to not just say Vietnamese, but to sound right.

So, What’s the Big Deal with Vietnamese i18n?

It’s the nuance. Vietnamese isn’t like dumping a few extra letters in. You’ve got diacritics – those little marks that change pronunciation and meaning entirely. Think ‘a’ versus ‘á’ versus ‘à’ versus ‘ã’ versus ‘ả’ versus ‘ạ’. Get one of those wrong, and your carefully crafted marketing message sounds like gibberish. Or worse, unintentionally rude. Polite phrasing, too. You don’t want your error messages to sound like a drill sergeant.

Polite phrasing: Vietnamese error messages should sound respectful. “Vui lòng nhập email” (Please enter email) not “Nhập email” (Enter email).

This is where most off-the-shelf solutions stumble. They treat language as a simple string replacement. But for something as culturally nuanced as Vietnamese, you need a system that handles character encoding correctly and allows for those specific grammatical structures.

The nestjs-i18n Approach: Beyond Basic Strings

The real trick here is using a library that plays nice with Unicode and offers a flexible resolver. nestjs-i18n fits the bill. It’s not some new, bleeding-edge thing, but it’s solid. The setup is straightforward, and thankfully, it handles the UTF-8 encoding for those Vietnamese characters like a champ. No fiddling with bizarre character maps required.

First, you’ll want to grab the package:

npm install nestjs-i18n

Then, you structure your translation files. Think vi/validation.json and en/validation.json for validation errors, and similarly for general response messages. This keeps things organized.

Here’s a peek at what your vi/validation.json might look like:

{
"EMAIL_INVALID": "Email không hợp lệ",
"PASSWORD_MIN_LENGTH": "Mật khẩu phải có ít nhất 6 ký tự",
"USER_NOT_FOUND": "Không tìm thấy người dùng",
"EMAIL_EXISTS": "Email đã tồn tại",
"FORBIDDEN": "Bạn không có quyền truy cập"
}

And for general responses:

{
"LOGIN_SUCCESS": "Đăng nhập thành công",
"REGISTER_SUCCESS": "Đăng ký thành công",
"LOGOUT_SUCCESS": "Đăng xuất thành công"
}

See that? Proper Vietnamese characters, no problem. And the phrasing is more natural than a direct English translation would yield. It’s about building APIs that don’t just function, but communicate.

Auto-Detection: The “Zero Extra Code” Illusion

The author touts “zero extra code” for auto-detection, which is a slight exaggeration, but it’s close. By using the HeaderResolver and targeting the Accept-Language header, NestJS can indeed pick up the user’s preferred language directly from their browser request. This is the standard way to handle it.

// app.module.ts
import { I18nModule, HeaderResolver } from 'nestjs-i18n';
import * as path from 'path';

@Module({
  imports: [
    I18nModule.forRoot({
      fallbackLanguage: 'vi',
      loaderOptions: {
        path: path.join(__dirname, '/i18n/'),
        watch: true,
      },
      resolvers: [new HeaderResolver(['accept-language'])],
    }),
    // ... other imports
  ],
})
export class AppModule {}

This means if a user’s browser is set to Vietnamese, the Accept-Language header will reflect that, and your NestJS app will serve up the Vietnamese translations automatically. No need for manual language selection in the UI for basic cases.

Handling Errors Gracefully (and in Vietnamese)

Where this really shines is in error handling. Instead of generic HTTP error messages, you can provide contextually relevant, translated errors. The HttpExceptionFilter example shows how to intercept exceptions and use the I18nContext to translate messages that are formatted as dot-notation keys (like validation.EMAIL_INVALID).

// http-exception.filter.ts
import { I18nContext } from 'nestjs-i18n';

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const i18n = I18nContext.current();
    const response = ctx.getResponse<Response>();
    const status = exception.getStatus();
    const message = exception.message;

    // Translate if the message is a dot-notation key like "validation.EMAIL_INVALID"
    const translated = i18n?.translate(message) ?? message;

    response.status(status).json({
      statusCode: status,
      message: translated,
      timestamp: new Date().toISOString(),
    });
  }
}

This is huge. It means your error messages are not only localized but also potentially provide more helpful, actionable information to the user, all while maintaining that crucial polite tone. Placeholders for dynamic values – like {min} or {max} in password length requirements – work smoothly too, so you can interpolate values directly into your translated strings.

Who is Actually Making Money Here?

Let’s be honest. The libraries themselves are usually open-source, free. The money comes from the application that uses them. For developers building SaaS products, e-commerce platforms, or any service targeting a global audience, proper internationalization isn’t an option; it’s a necessity. Companies that invest in genuine localization — not just clumsy translation — win market share. They build trust. They cater to diverse user bases with respect. So, while nestjs-i18n doesn’t directly profit from this tutorial, the developers who implement it successfully can, and will, build more successful, profitable applications. The real win is for the end-users who get a better, more culturally appropriate experience.


🧬 Related Insights

Frequently Asked Questions

What does nestjs-i18n actually do? nestjs-i18n is a NestJS module that provides internationalization (i18n) features, allowing you to easily manage translations for multiple languages within your application and automatically serve the correct language based on request headers.

Will this replace my job as a developer? No. Implementing i18n requires development effort. This guide and the nestjs-i18n library streamline the process, making it more efficient and less error-prone, but the core development work remains. It helps you build better, more accessible applications.

Is this setup complex for developers? While setting up i18n adds a layer of complexity, nestjs-i18n aims to simplify it. The provided setup with HeaderResolver and structured JSON files is relatively straightforward for experienced NestJS developers, requiring minimal custom code for basic auto-detection.

Written by
DevTools Feed Editorial Team

Curated insights, explainers, and analysis from the editorial team.

Frequently asked questions

What does `nestjs-i18n` actually do?
`nestjs-i18n` is a NestJS module that provides internationalization (i18n) features, allowing you to easily manage translations for multiple languages within your application and automatically serve the correct language based on request headers.
Will this replace my job as a developer?
No. Implementing i18n requires development effort. This guide and the `nestjs-i18n` library streamline the process, making it more efficient and less error-prone, but the core development work remains. It helps you build better, more accessible applications.
Is this setup complex for developers?
While setting up i18n adds a layer of complexity, `nestjs-i18n` aims to simplify it. The provided setup with `HeaderResolver` and structured JSON files is relatively straightforward for experienced NestJS developers, requiring minimal custom code for basic auto-detection.

Worth sharing?

Get the best Developer Tools stories of the week in your inbox — no noise, no spam.

Originally reported by dev.to

Stay in the loop

The week's most important stories from DevTools Feed, delivered once a week.