Skip to content

Web Translation Guide

This guide explains how to add and maintain translations in the OktaPT-FE web application.

File Structure & Locations

Translation files are stored in:

OktaPT-FE/public/locales/
  en/
    common.json    # English (reference locale)
  ru/
    common.json    # Russian
  • Supported locales: en (English), ru (Russian)
  • Reference locale: English (en) is the source of truth
  • Namespace: All translations use the common namespace
  • Library: Uses next-i18next for internationalization

Adding New Translations

Step-by-Step Process

  1. Add the key to the English file first (OktaPT-FE/public/locales/en/common.json)
  2. Add the same key to the Russian file (OktaPT-FE/public/locales/ru/common.json)
  3. Maintain identical key order - the key must be in the same position in both files
  4. Run validation to verify both files are in sync

Example

To add a new "logout confirmation" message:

English (en/common.json):

{
  "header": {
    "auth": {
      "login": "Login",
      "signup": "Sign up",
      "logout": "Logout",
      "logoutConfirm": "Are you sure you want to log out?"
    }
  }
}

Russian (ru/common.json):

{
  "header": {
    "auth": {
      "login": "Войти",
      "signup": "Регистрация",
      "logout": "Выйти",
      "logoutConfirm": "Вы уверены, что хотите выйти?"
    }
  }
}

Key Naming Conventions

Hierarchical Structure

Keys are organized hierarchically by feature or page:

{
  "login": { ... },
  "signup": { ... },
  "patientDashboard": { ... },
  "doctorDashboard": { ... },
  "exerciseLibrary": { ... }
}

Naming Rules

  • Use camelCase for all keys: forgotPassword, noAccount, sendVerificationCode
  • Group related translations under a parent key
  • Use descriptive names that indicate purpose

Common Patterns

Pattern Example Use Case
feature.title login.title Page or section titles
feature.subtitle login.subtitle Secondary headings
feature.buttonName login.submit Button labels
feature.loading login.loading Loading states
feature.errors.errorType login.errors.failed Error messages
feature.form.fieldName profile.personalData.firstName Form field labels

Variable Interpolation

Syntax

Use double curly braces for variables: {{variableName}}

Examples from the Codebase

Greeting with name:

{
  "patientDashboard": {
    "greeting": "Hello {{name}}!",
    "greeting_fallback": "Hello Patient!"
  }
}

Date display:

{
  "doctorDashboard": {
    "dateTime": {
      "connectedSince": "Connected since {{date}}"
    }
  }
}

Multiple variables:

{
  "healthcareTeam": {
    "connectionRequests": {
      "pendingRequestTo": "Pending request to {{userType}} {{name}}",
      "wantsToConnect": "{{userType}} {{name}} wants to connect"
    }
  }
}

Count/number display:

{
  "pastWorkouts": {
    "workoutDetails": {
      "recording_multiple": "{{number}}"
    }
  }
}

Using Variables in Components

Import the translation hook and use the t() function:

import { useTranslation } from "next-i18next";

function PatientDashboard({ user }) {
  const { t } = useTranslation("common");

  return (
    <h1>{t("patientDashboard.greeting", { name: user.firstName })}</h1>
  );
}

For translations without variables:

<button>{t("login.submit")}</button>

With multiple variables:

t("healthcareTeam.connectionRequests.pendingRequestTo", {
  userType: request.requestedBy === "DOCTOR" ? t("common.patient") : "",
  name: `${request.patient.firstName} ${request.patient.lastName}`,
})

Validation

Running the Validator

After making changes to locale files, run from the OktaPT-FE directory:

npm run i18n:check

What the Validator Checks

  1. Missing keys: Keys present in English but missing in Russian
  2. Extra keys: Keys present in Russian but not in English
  3. Key order: Keys must be in the same position in both files

Understanding Error Messages

Missing keys:

❌ Missing keys in ru/common.json:
   - newFeature.title
   - newFeature.description
Fix: Add the missing keys to the Russian file in the same position as English.

Extra keys:

⚠️  Extra keys in ru/common.json (not in en):
   - oldFeature.deprecated
Fix: Remove the extra keys from Russian, or add them to English if they should exist.

Order mismatch:

🔀 Key order mismatch in ru/common.json (3 positions):
   Position 42: expected "features.title", found "features.subtitle"
Fix: Reorder the keys in Russian to match the English file exactly.

Success Output

✅ ru/common.json is in sync with en/common.json (1452 keys, order matches)

Best Practices

  1. Always add translations to both files simultaneously - never commit with only one locale updated
  2. Keep English as the source of truth - add new keys to English first, then translate
  3. Preserve key order - when adding keys, insert them in the same position in both files
  4. Use meaningful fallbacks - provide _fallback variants for dynamic content (e.g., greeting_fallback)
  5. Run validation before committing - ensure npm run i18n:check passes
  6. Don't hardcode text in components - always use the t() function for user-facing strings
  7. Handle missing values - always provide fallback values when the variable might be undefined:
    t("greeting", { name: user?.name || "Guest" })