INTERNATIONALIZATION.md
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.
Vue I18n is already configured and ready to use! The setup includes:
useI18n()$t() in templates$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>
<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>
<script>
export default {
computed: {
title() {
return this.$t('sessions.title');
}
},
methods: {
handleError() {
console.error(this.$t('errors.loadingFailed'));
}
}
};
</script>
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"
}
}
<template>
<div>
<h2>{{ $t('newFeature.title') }}</h2>
<p>{{ $t('newFeature.description') }}</p>
</div>
</template>
The LanguageSwitcher component automatically detects and sets the best language using this priority order:
navigator.language)
en-US ā en, es-MX ā es)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>
The internationalization system is designed to be shared across all Arkime applications (viewer, cont3xt, parliament, wiseService).
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, /* ... */ }
});
<template>
<div>
<LanguageSwitcher />
</div>
</template>
<script setup>
import LanguageSwitcher from '@common/LanguageSwitcher.vue';
</script>
<template>
<h1>{{ $t('navigation.stats') }}</h1>
<button>{{ $t('common.search') }}</button>
</template>
If an application needs specific translations not shared across all apps:
cont3xt-specific.json)import commonEnglish from '@common/locales/en.json';
import cont3xtEnglish from './locales/cont3xt-en.json';
const englishMessages = { ...commonEnglish, ...cont3xtEnglish };
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
$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"
ā Don't do this:
<button>Search Sessions</button>
ā Do this:
<button>{{ $t('search.searchSessions') }}</button>
ā Don't do this:
$t('btn1') // unclear
$t('text') // too generic
ā Do this:
$t('sessions.exportButton')
$t('search.timeRangeLabel')
{
"sessions": {
"title": "Sessions",
"export": "Export Sessions",
"filter": "Filter Sessions",
"columns": {
"startTime": "Start Time",
"endTime": "End Time",
"protocol": "Protocol"
}
}
}
Vue I18n will automatically fall back to English if a translation is missing.
{
"sessions": {
"count": "no sessions | {count} session | {count} sessions"
}
}
<template>
<p>{{ $t('sessions.count', sessionCount) }}</p>
</template>
{
"welcome": "Welcome {username} to Arkime!"
}
<template>
<h1>{{ $t('welcome', { username: user.name }) }}</h1>
</template>
sessions.title not session.title)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
ā āāā LanguageSwitcher.vue # Shared language selector component
ā āāā I18nExample.vue # Shared usage examples
āāā viewer/vueapp/src/
āāā main.js # Vue I18n configuration
To add i18n to existing components:
$t() callsBefore:
<button>Save Changes</button>
After:
<button>{{ $t('common.save') }}</button>
And add to locale files:
{
"common": {
"save": "Save"
}
}
common/vueapp/I18nExample.vue for practical examplesHappy internationalizing! š