ShipNow
Features

I18n

ShipNow has built-in i18n(internationalization) support. It supports multiple languages out of the box.

Overview

ShipNow's i18n feature includes:

  • ➕ Easy to add a new language
  • ⚙️ Centralized locale configuration
  • 💻 Easy usage in server or client components
  • 🔍 Automatic SEO metadata for different languages
  • 🔀 Built-in Language switcher, Link components
  • 🧭 Automatic language detection and routing redirection

Add a New Language

  1. Add the language to config/locales.ts:
config/locales.ts
export const locales = [
  { code: 'en', name: 'English' },
  { code: 'zh-CN', name: '简体中文' },
  { code: 'zh-TW', name: '繁體中文' }, // Add this line
] as const;

The new language will automatically be available in the language switcher.

  1. Create a new translation file in messages/:
cp messages/en.json messages/zh-TW.json
  1. Use the following Prompt, ask AI to translate the content:
Translate the following content to Traditional Chinese:
 
{
  "navigation": {
    "features": "Features",
    "pricing": "Pricing",
  },
  "seo": {
    "title": "ShipNow - Next.js AI SaaS Template",
    "description": "...",
  }
}
  1. Update result content back to the translation file:
messages/zh-TW.json
{
  "navigation": {
    "features": "功能",
    "pricing": "價格"
  },
  "seo": {
    "title": "ShipNow - Next.js AI SaaS 模板",
    "description": "..."
  }
}

Update Translation Content

ShipNow's default language is English. You can update the translation content in messages/en.json.

messages/en.json
{
  "navigation": {
    "features": "Features",
    "pricing": "Pricing"
  },
  "seo": {
    "title": "ShipNow - Next.js AI SaaS Template",
    "description": "..."
  }
}

Use In Server Components

To use in server components, use the getTranslations function:

import { getTranslations } from 'next-intl/server';
 
export async function MyServerComponent() {
  const t = await getTranslations('navigation');
  
  return <h1>{t('features')}</h1>;
}

Use In Client Components

To use in client components, use the useTranslations hook:

'use client';
 
import { useTranslations } from 'next-intl';
 
export function MyClientComponent() {
  const t = useTranslations('navigation');
  
  return <button>{t('features')}</button>;
}

Language Switcher Component

ShipNow includes a built-in language switcher component that allows users to change languages:

import { LanguageSwitcher } from '@/components/LanguageSwitcher';
 
export function MyComponent() {
  return <LanguageSwitcher />;
}

Use the Link component to navigate to the URL with the current language:

// Import from `@/i18n/routing`, not `next/link`
import { Link } from '@/i18n/routing'; 
 
export function MyComponent() {
  return (
    // If it's en, generate /docs
    // If it's zh-CN, generate /zh-CN/docs
    <Link href="/docs">
      Documentation
    </Link>
  );
}

SEO

ShipNow automatically handles SEO metadata for different languages. The metadata is defined in the translation files and used in the layout:

app/[lang]/layout.tsx
export async function generateMetadata() {
  const t = await getTranslations('seo');
  
  return {
    title: {
      default: t('title'),
      template: `%s | ${process.env.NEXT_PUBLIC_APP_NAME}`,
    },
    description: t('description'),
    keywords: t('keywords'),
  };
}

This ensures that search engines receive the correct metadata for each language.

Only one language?

If your system has only one language, you can:

  1. Remove the extra language in config/locales.ts:
config/locales.ts
export const locales = [
  { code: 'en', name: 'English' },
  { code: 'zh-CN', name: '简体中文' }, // Remove this line
] as const;

The language switcher will not display if there is only one language.

  1. Directly use any text in the component file, without needing to use getTranslations or useTranslations.

Need Help?

If you need help with i18n:

On this page