Создание многоязычной платформы калькуляторов с Next.js 15

Подробный анализ создания высокопроизводительной многоязычной платформы калькуляторов с Next.js 15, React 19 и next-intl, включая реализацию интернационализации, SEO-оптимизацию и оптимизацию производительности.

6 мин чтения
Next.jsReactИнтернационализацияSEOОптимизация ПроизводительностиTypeScript

Привет, коллеги-разработчики! 👋

Если вы когда-либо пытались создать веб-сайт, который должен работать для пользователей по всему миру, вы знаете, насколько это может быть сложно. Недавно я отправился в путешествие по созданию Free Calculators - платформы, которая обслуживает пользователей на 12 разных языках, и позвольте сказать, это было настоящее приключение!

В этом посте я хочу поделиться реальной историей создания этой многоязычной платформы калькуляторов. Не просто версией "вот что мы сделали", а версией "вот что действительно произошло, что пошло не так, и чему мы научились". Потому что, честно говоря, создание для глобальной аудитории - это не прогулка в парке.

Почему Мы Создали Это (И Почему Это Важно)

Представьте себе: Вы создаете приложение-калькулятор. Довольно просто, верно? Но затем вы понимаете, что кому-то в Японии может понадобиться японская версия, кому-то в Бразилии может понравиться португальский, а ваши немецкие пользователи определенно хотят, чтобы их числа форматировались по-немецки (1.234,56 вместо 1,234.56). Внезапно ваш простой калькулятор становится сложным международным проектом.

Именно это произошло с нами. Мы начали с базового калькулятора и в итоге создали платформу, которая обслуживает пользователей разных культур, языков и форматов чисел. И знаете что? Это стал одним из самых полезных проектов, над которыми я работал.

Решения Технологического Стека: Почему Мы Выбрали Эти Инструменты

Почему Next.js 15?

Честно говоря, когда Next.js 15 впервые вышел, мы немного колебались. В конце концов, "если не сломалось, не чини", верно? Но когда мы увидели новый App Router и интеграцию React 19, мы решили сделать прыжок. Это оказалось мудрым выбором.

// Вот как мы настроили нашу маршрутизацию
export const routing = defineRouting({
  locales: [
    'en',
    'zh',
    'ja',
    'ko',
    'fr',
    'de',
    'es',
    'pt',
    'ru',
    'ar',
    'hi',
    'it',
  ],
  defaultLocale: 'en',
  localePrefix: 'as-needed', // Эта настройка спасла нас от множества головных болей
  localeDetection: true,
});

React 19: Стоит Ли Обновляться?

Короткий ответ: Абсолютно! Длинный ответ: Мы столкнулись с некоторыми проблемами совместимости, но улучшения производительности новых функций значительны. Особенно улучшения в Suspense и конкурентных функциях сделали наш пользовательский опыт намного лучше.

TypeScript: Наш Спаситель

Я не могу представить управление файлами переводов для 12 языков без TypeScript. Безопасность типов дала нам уверенность при рефакторинге, особенно при работе со сложными вложенными объектами переводов.

// Вот как мы определяем наши типы переводов
interface TranslationKeys {
  nav: {
    siteName: string;
    home: string;
    calculators: string;
  };
  common: {
    calculate: string;
    clear: string;
    result: string;
  };
}

Реализация Интернационализации: Реальные Вызовы и Решения

Вызов 1: Сложность Определения Языка

Вы можете подумать: "Определение языка? Легко!" Но это не так. Пользователи могут заходить с разных устройств, использовать VPN или иметь специфические языковые предпочтения. Мы потратили много времени на совершенствование нашей логики определения языка.

// Наша конфигурация middleware
import createMiddleware from 'next-intl/middleware';
import { routing } from '@/i18n/routing';

export default createMiddleware(routing);

export const config = {
  matcher: '/((?!api|trpc|_next|_vercel|.*\\..*).*)',
};

Вызов 2: Управление Файлами Переводов

Управление файлами переводов для 12 языков - это как управление 12 разными проектами. Мы разработали несколько скриптов автоматизации, чтобы помочь нам:

// Наш скрипт управления переводами
const addMissingTranslations = async () => {
  const baseTranslations = await loadTranslations('en');
  const allLocales = await getAllLocales();

  for (const locale of allLocales) {
    const existingTranslations = await loadTranslations(locale);
    const missingKeys = findMissingKeys(baseTranslations, existingTranslations);

    if (missingKeys.length > 0) {
      console.log(`Missing keys in ${locale}:`, missingKeys);
      await addMissingKeys(locale, missingKeys);
    }
  }
};

Вызов 3: Ловушка Форматирования Чисел

Это был один из самых интересных вызовов. Знаете ли вы, что в разных странах разные форматы чисел? Германия использует запятые как разделители десятичных знаков, США используют точки. Мы столкнулись со множеством проблем при работе с валютными расчетами, пока не реализовали правильное локализованное форматирование.

SEO Оптимизация: Заставляем Поисковые Системы Любить Нас

Сила Статической Генерации Сайтов

Мы решили использовать статическую генерацию сайтов (SSG), что может быть лучшим решением, которое мы когда-либо принимали. Страницы не только молниеносно быстрые, но и результаты SEO также отличные.

// Генерация статических страниц для каждого языка
export const dynamic = 'force-static';

export function generateStaticParams() {
  return routing.locales
    .filter(locale => locale !== routing.defaultLocale)
    .map(locale => ({ locale }));
}

Искусство Генерации Метаданных

Генерация правильных метаданных для каждого языка требует некоторой тонкости. Мы разработали систему для автоматической генерации SEO-дружественных метаданных:

export async function generateMetadata({
  params,
}: {
  params: Promise<{ locale: string }>;
}): Promise<Metadata> {
  const { locale } = await params;
  const t = await getTranslations({ locale, namespace: 'Home' });

  return {
    title: t('title'),
    description: t('description'),
    openGraph: {
      title: t('title'),
      description: t('description'),
      locale: locale,
    },
  };
}

Оптимизация Производительности: Делаем Пользовательский Опыт Плавным

Важность Оптимизации Изображений

Мы потратили много времени на оптимизацию загрузки изображений. Принятие форматов AVIF и WebP улучшило скорость загрузки наших страниц на 40%.

// Конфигурация изображений в next.config.ts
images: {
  formats: ['image/avif', 'image/webp'],
  domains: ['freecalculators.app'],
  deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
  imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
}

Стратегия Кэширования: Наше Секретное Оружие

Реализация правильной стратегии кэширования потребовала некоторых проб и ошибок. В итоге мы пришли к многоуровневому подходу кэширования:

async headers() {
  return [
    // Сильное кэширование для статических ресурсов
    {
      source: '/(.*).(js|css|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot)',
      headers: [{
        key: 'Cache-Control',
        value: 'public, max-age=31536000, immutable',
      }],
    },
    // Согласованное кэширование для страниц
    {
      source: '/(.*)',
      headers: [{
        key: 'Cache-Control',
        value: 'public, max-age=0, must-revalidate',
      }],
    },
  ];
}

Дизайн Пользовательского Опыта: Заставляем Всех Чувствовать Себя Желанными

Вызов Адаптивного Дизайна

Обеспечение того, чтобы наши калькуляторы идеально работали на всех устройствах, является постоянным вызовом. Мы приняли подход mobile-first:

// Адаптивный макет mobile-first
<div className="flex flex-col md:flex-row gap-4">
  <div className="w-full md:w-1/2">
    {/* Интерфейс калькулятора */}
  </div>
  <div className="w-full md:w-1/2">
    {/* Отображение результатов */}
  </div>
</div>

Доступность: Больше Чем Просто Соответствие

Мы поняли, что доступность - это не просто правовое требование - это правильное дело. Мы добавили соответствующие ARIA-метки к каждому интерактивному элементу:

<button
  aria-label={t('common.calculate')}
  aria-describedby="calculator-help"
  className="bg-blue-600 text-white px-4 py-2 rounded"
>
  {t('common.calculate')}
</button>

Инструментарий Разработки: Делаем Разработку Более Эффективной

Мониторинг Ошибок: Наша Сеть Безопасности

Мы интегрировали Sentry для мониторинга ошибок, что помогло нам обнаружить множество проблем, которых мы никогда не ожидали:

export default withSentryConfig(withNextIntl(nextConfig), {
  org: 'my-projects-pd',
  project: 'free-calculators',
  widenClientFileUpload: true,
  disableLogger: true,
  automaticVercelMonitors: true,
});

Автоматизированное Управление Переводами

Мы разработали несколько скриптов для управления файлами переводов, и эти скрипты теперь являются неотъемлемой частью нашего рабочего процесса.

Уроки, Которые Мы Изучили

1. Думайте Об Интернационализации С Самого Начала

Если вы думаете, что вам может понадобиться многоязычная поддержка, проектируйте это с самого начала. Добавление интернационализации позже намного сложнее, чем проектирование ее с самого начала.

2. Пользовательский Опыт Превыше Технического Показухи

Мы потратили много времени на оптимизацию производительности, но в конечном итоге пользователи больше всего заботятся о том, интуитивен ли интерфейс и точны ли вычисления.

3. Автоматизация - Ключ

Ручное управление переводами для 12 языков нереально. Скрипты автоматизации - это спасательный круг нашего проекта.

4. Тестируйте, Тестируйте и Тестируйте Снова

Разные языки имеют разную длину текста, разные форматы чисел и разные культурные ожидания. Тщательное тестирование обязательно.

Будущие Планы

Мы рассматриваем возможность добавления больше языков, улучшения нашего процесса управления переводами и изучения возможностей ИИ-ассистированного перевода. Но самое главное, мы хотим продолжать предоставлять пользователям лучший опыт калькулятора.

Заключение

Создание многоязычного веб-приложения - это вызов, но также очень полезный опыт. Благодаря умным технологическим решениям и множеству тестов, мы успешно создали платформу, которая действительно обслуживает глобальных пользователей.

Если вы рассматриваете создание многоязычного приложения, я надеюсь, что эта статья даст вам некоторое вдохновение. Помните, каждый вызов - это возможность обучения, и каждая ошибка - это ступенька к успеху.


Ссылка на Проект: https://www.freecalculators.app Технологический Стек: Next.js 15, React 19, TypeScript, Tailwind CSS, next-intl