Arkime Internationalization Guide
July 6, 2026 ยท View on GitHub
This guide explains how to use and contribute to internationalization (i18n) in the Arkime viewer application using Vue I18n v11.
Contributing to translations? See the Contributing Guide for information on how to add new languages or improve existing translations.
๐ Quick Start
Vue I18n is already configured and ready to use! The setup includes:
- Smart locale detection: localStorage โ browser language โ fallback to English
- 9 supported languages: English, Spanish, French, German, Japanese, Korean, Chinese, Estonian, Brazilian Portuguese
- Composition API: Modern Vue 3 approach with
useI18n() - Global injection: Use
$t()in templates - Language persistence: User preferences saved in localStorage
- Shared components: LanguageSwitcher and translation files available across all Arkime applications
๐ Using Translations in Components
1. Template Usage (Global $t function)
<template>
<div>
<!-- Simple translation -->
<h1>{{ $t('navigation.sessions') }}</h1>
<!-- In attributes -->
<input :placeholder="$t('search.expression')" />
<!-- In directives -->
<button :title="$t('common.search')">Search</button>
</div>
</template>
2. Composition API Usage
<script setup>
import { useI18n } from 'vue-i18n';
const { t, locale } = useI18n();
// Use in computed properties
const buttonText = computed(() => t('common.save'));
// Use in methods
const showMessage = () => {
alert(t('errors.networkError'));
};
// Access current locale
console.log('Current language:', locale.value);
</script>
3. Options API Usage
<script>
export default {
computed: {
title() {
return this.$t('sessions.title');
}
},
methods: {
handleError() {
console.error(this.$t('errors.loadingFailed'));
}
}
};
</script>
๐ง Adding New Translations
1. Add to Translation Files
Update all locale files in common/vueapp/locales/:
// en.json
{
"newFeature": {
"title": "New Feature",
"description": "This is a new feature"
}
}
// es.json
{
"newFeature": {
"title": "Nueva Funcionalidad",
"description": "Esta es una nueva funcionalidad"
}
}
2. Use in Components
<template>
<div>
<h2>{{ $t('newFeature.title') }}</h2>
<p>{{ $t('newFeature.description') }}</p>
</div>
</template>
๐ Language Switching
Automatic Language Detection
The LanguageSwitcher component automatically detects and sets the best language using this priority order:
- Saved preference (localStorage): If user previously selected a language
- Browser language: Detects browser's default language (
navigator.language)- Handles locale variants (e.g.,
en-USโen,es-MXโes) - Only sets if we support the base language code
- Handles locale variants (e.g.,
- Fallback to English: If no saved preference and browser language not supported
Using the Language Switcher Component
The LanguageSwitcher component uses the country-code-emoji package to generate flag emojis dynamically based on country codes.
<template>
<div>
<!-- Add anywhere in your template -->
<LanguageSwitcher />
</div>
</template>
<script setup>
import LanguageSwitcher from '@common/LanguageSwitcher.vue';
</script>
๐ Using i18n in Other Arkime Applications
The internationalization system is designed to be shared across all Arkime applications (viewer, cont3xt, parliament, wiseService).
Setting up i18n in Other Apps
- Import shared translation files:
import { createI18n } from 'vue-i18n';
import english from '@common/locales/en.json';
import spanish from '@common/locales/es.json';
// ... other languages
const i18n = createI18n({
messages: { en: english, es: spanish, /* ... */ }
});
- Use the shared LanguageSwitcher component:
<template>
<div>
<LanguageSwitcher />
</div>
</template>
<script setup>
import LanguageSwitcher from '@common/LanguageSwitcher.vue';
</script>
- Use translations in your components:
<template>
<h1>{{ $t('navigation.stats') }}</h1>
<button>{{ $t('common.search') }}</button>
</template>
Application-Specific Translations
If an application needs specific translations not shared across all apps:
- Create app-specific locale files (e.g.,
cont3xt-specific.json) - Merge with common translations:
import commonEnglish from '@common/locales/en.json';
import cont3xtEnglish from './locales/cont3xt-en.json';
const englishMessages = { ...commonEnglish, ...cont3xtEnglish };
๐ Translation Key Organization
Our translations are organized hierarchically:
common.* - Universal UI elements (save, cancel, etc.)
navigation.* - Menu items and navigation
sessions.* - Session-related terms
search.* - Search functionality
stats.* - Statistics and metrics
errors.* - Error messages
Examples:
$t('common.search') // "Search"
$t('navigation.sessions') // "Sessions"
$t('sessions.startTime') // "Start Time"
$t('search.expression') // "Search Expression"
$t('stats.captureStats') // "Capture Statistics"
$t('errors.loadingFailed') // "Failed to load data"
๐ฏ Best Practices
1. Always Use Translation Keys
โ Don't do this:
<button>Search Sessions</button>
โ Do this:
<button>{{ $t('search.searchSessions') }}</button>
2. Keep Keys Descriptive
โ Don't do this:
$t('btn1') // unclear
$t('text') // too generic
โ Do this:
$t('sessions.exportButton')
$t('search.timeRangeLabel')
3. Group Related Translations
{
"sessions": {
"title": "Sessions",
"export": "Export Sessions",
"filter": "Filter Sessions",
"columns": {
"startTime": "Start Time",
"endTime": "End Time",
"protocol": "Protocol"
}
}
}
4. Handle Missing Translations Gracefully
Vue I18n will automatically fall back to English if a translation is missing.
๐ Advanced Usage
1. Pluralization (when needed)
{
"sessions": {
"count": "no sessions | {count} session | {count} sessions"
}
}
<template>
<p>{{ $t('sessions.count', sessionCount) }}</p>
</template>
2. Variable Interpolation
{
"welcome": "Welcome {username} to Arkime!"
}
<template>
<h1>{{ $t('welcome', { username: user.name }) }}</h1>
</template>
๐ Troubleshooting
Translation Not Showing?
- Check the key exists in all locale files
- Verify the path is correct (
sessions.titlenotsession.title) - Check console for i18n warnings
- Ensure i18n is imported in main.js
Language Not Persisting?
- Check localStorage permissions
- Verify LanguageSwitcher sets localStorage correctly
- Check browser language detection logic
๐ File Structure
arkime/
โโโ INTERNATIONALIZATION.md # This guide
โโโ CONTRIBUTING.md # Includes i18n contribution guidelines
โโโ common/vueapp/
โ โโโ locales/ # Shared translation files
โ โ โโโ en.json # English (default)
โ โ โโโ es.json # Spanish
โ โ โโโ fr.json # French
โ โ โโโ de.json # German
โ โ โโโ ja.json # Japanese
โ โ โโโ ko.json # Korean
โ โ โโโ zh.json # Chinese
โ โ โโโ et.json # Estonian
โ โ โโโ pt-BR.json # Brazilian Portuguese
โ โ โโโ x-pl.json # Pig-Latin (testing)
โ โโโ LanguageSwitcher.vue # Shared language selector component
โ โโโ I18nExample.vue # Shared usage examples
โโโ viewer/vueapp/src/
โโโ main.js # Vue I18n configuration
๐ Migration Guide
To add i18n to existing components:
- Replace hardcoded text with
$t()calls - Add translation keys to all locale files
- Test with different languages
- Add LanguageSwitcher where appropriate
Example Migration:
Before:
<button>Save Changes</button>
After:
<button>{{ $t('common.save') }}</button>
And add to locale files:
{
"common": {
"save": "Save"
}
}
๐ Getting Help
- Check the Vue I18n documentation
- Look at
common/vueapp/I18nExample.vuefor practical examples - Test your translations with the LanguageSwitcher component
Happy internationalizing! ๐