How to Add New Languages for i18n Support in Vue-Color-Avatar

To add new languages for i18n support in vue-color-avatar, extend the Locale enum in src/enums/index.ts, create a translation bundle in src/i18n/locales/{lang}/index.ts, and register the new messages in src/i18n/index.ts.

The vue-color-avatar project uses vue-i18n to provide multilingual UI text for its avatar generator interface. If you want to add new languages for i18n support beyond the built-in English and Chinese, you must extend three core parts of the localization infrastructure: the locale enum, the message bundles, and the i18n instance configuration.

Understanding the i18n Architecture

Before adding a language, understand how the project structures its internationalization:

  • src/enums/index.ts – Defines the Locale enum that type-safely identifies supported languages (e.g., Locale.EN, Locale.ZH).
  • src/i18n/locales/ – Contains one folder per language (e.g., en/, zh/). Each folder exports an object with identical keys for UI text, labels, and actions.
  • src/i18n/index.ts – Bootstraps the vue-i18n plugin, imports all message bundles, and determines the active locale based on browser detection or fallback logic.

Step 1: Extend the Locale Enum

Add your new language identifier to the Locale enum in src/enums/index.ts. This ensures type safety throughout the application.

// src/enums/index.ts
export const enum Locale {
  ZH = 'zh',
  EN = 'en',
  ES = 'es',   // ← Add new language code here
}

Step 2: Create the Translation Bundle

Create a new directory for your language under src/i18n/locales/ (e.g., src/i18n/locales/es/). Inside, create an index.ts file that exports an object matching the structure of existing bundles like en or zh.

The bundle must include keys for action, label, widgetType, wrapperShape, and text, using the WidgetType enum for widget keys.

// src/i18n/locales/es/index.ts
import { WidgetType } from '@/enums'

export const es = {
  action: {
    undo: 'Deshacer',
    redo: 'Rehacer',
    flip: 'Voltear',
    code: 'Código',
    randomize: 'Aleatorio',
    download: 'Descargar',
    downloadMultiple: 'Generar varios',
    copyCode: 'Copiar',
    copied: 'Copiado',
    downloading: 'Descargando',
    close: 'Cerrar',
  },
  label: {
    wrapperShape: 'Forma del avatar',
    borderColor: 'Color del borde',
    backgroundColor: 'Color de fondo',
    colors: 'Colores',
  },
  widgetType: {
    [WidgetType.Face]: 'Cara',
    [WidgetType.Tops]: 'Cabello / Accesorios',
    [WidgetType.Ear]: 'Oreja',
    [WidgetType.Earrings]: 'Pendientes',
    [WidgetType.Eyebrows]: 'Cejas',
    [WidgetType.Eyes]: 'Ojos',
    [WidgetType.Nose]: 'Nariz',
    [WidgetType.Glasses]: 'Gafas',
    [WidgetType.Mouth]: 'Boca',
    [WidgetType.Beard]: 'Barba',
    [WidgetType.Clothes]: 'Ropa',
  },
  wrapperShape: {
    circle: 'Círculo',
    square: 'Cuadrado',
    squircle: 'Cuadrado redondeado',
  },
  text: {
    codeModalTitle: 'Código',
    downloadTip: 'Mantén pulsado o haz clic derecho para guardar',
    downloadMultiple: 'Descargar todo',
    downloadingMultiple: 'Descargando',
    downloadMultipleTip: 'Avatares generados automáticamente',
    regenerate: 'Regenerar',
  },
}

Step 3: Register the New Language

Import your new bundle and add it to the messages object in src/i18n/index.ts. You can also extend the browser language detection logic if desired.

// src/i18n/index.ts
import { createI18n } from 'vue-i18n'
import { Locale } from '@/enums'
import { en } from './locales/en'
import { zh } from './locales/zh'
import { es } from './locales/es'   // ← Import new language

const messages = { en, zh, es }      // ← Add to messages map

// Optional: Add detection for Spanish
const [locale, fallbackLocale] = /^zh\b/.test(window.navigator.language)
  ? [Locale.ZH, Locale.EN]
  : /^es\b/.test(window.navigator.language)
    ? [Locale.ES, Locale.EN]
    : [Locale.EN, Locale.ZH]

export const i18n = createI18n({
  locale,
  fallbackLocale,
  messages,
})

Step 4: Update the UI Language Selector

The project includes a language selector in the configurator UI. Locate the component that renders language options (typically in the header or settings panel) and add the new Locale.ES option to the available choices so users can manually switch languages.

Step 5: Verify Your Implementation

Start the development server and test the new translations:

pnpm dev

# or

npm run dev

Switch your browser language to the new locale or use the UI selector. Verify that all UI strings appear correctly and that fallback logic works if translations are missing.

Summary

  • Extend the enum: Add your language code to Locale in src/enums/index.ts to enable type-safe references throughout the app.
  • Create the bundle: Mirror the structure of existing locales in src/i18n/locales/{lang}/index.ts, ensuring all action, label, widgetType, wrapperShape, and text keys are present.
  • Register the messages: Import the new bundle into src/i18n/index.ts and add it to the messages object passed to createI18n().
  • Update the UI: Add the new locale to the language selector component so users can switch manually.
  • Test thoroughly: Run the dev server and verify translations render correctly across all avatar configuration options.

Frequently Asked Questions

What file structure should I follow when adding new languages for i18n support?

Create a new folder under src/i18n/locales/ named with your language code (e.g., es for Spanish, fr for French). Inside that folder, create an index.ts file that exports an object containing action, label, widgetType, wrapperShape, and text keys, mirroring the structure found in src/i18n/locales/en/index.ts.

Do I need to modify the auto-detection logic in src/i18n/index.ts?

No, modifying the auto-detection logic is optional. The existing code uses a regex test against window.navigator.language to choose between Chinese and English defaults. If you want the app to automatically detect your new language, add a regex check (e.g., /^es\b/.test(window.navigator.language)) to the conditional chain. Otherwise, users can manually select the language via the UI selector.

How do I ensure type safety when adding translations?

Always add your new language to the Locale enum in src/enums/index.ts first. This enum is used throughout the application to type-check locale references. When creating your message bundle, copy the structure from an existing locale (like en or zh) to ensure you include all required keys, preventing runtime missing-translation errors.

Can I add regional variants like es-MX or pt-BR?

Yes, you can add regional variants by using the full locale code as the folder name (e.g., src/i18n/locales/es-MX/ or src/i18n/locales/pt-BR/). Add the corresponding entry to the Locale enum (e.g., ES_MX = 'es-MX'), and import the bundle in src/i18n/index.ts. Note that you may need to adjust the auto-detection regex to handle the hyphenated format (e.g., /^es\b/ will match es-MX due to the word boundary).

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →