i18n
Internationalisation (i18n) provides a way for you to customise your shop to accommodate users from different countries.
Locales
The i18n configuration affects language and currency. It's important that the app's configuration matches the settings of the system you connect to. Otherwise, you'll receive incorrect data or data in the wrong language.
Configuration:
- Locale settings must match PlentyONE system settings
fallbackLocaleanddefaultLocaleare determined dynamically from theDEFAULTLANGUAGEenvironment variable (defaults to English if not set or invalid)- All locale files are located in
apps/web/app/lang/as<locale>.json - Locales are dynamically loaded via
getLocales()inapps/web/app/configuration/i18n.config.ts - To update configuration, modify
i18n.config.tsandvueI18n.config.ts
INFO
By default, the app ships with English as the default locale and German as a second locale.
Supported locales:
de, en, bg, fr, it, es, tr, nl, pl, pt, nn, ro, da, se, cz, ru, sk, cn, vn
Localization Editor
The shop now includes a localization editor that allows users to activate languages and edit translations directly per language. This editor provides a user-friendly interface for managing all customer-facing translations without needing to manually edit JSON files.
Shop Translations
The localization function t(...) is now auto-imported and auto-completed in all Vue components. You no longer need to manually import or inject t—just use it directly in your templates and <script setup> blocks.
Usage Example
Before (manual import/injection):
<template>
<div>{{ t("your.translation.key") }}</div>
</template>
<script setup lang="ts">
const { t } = useI18n(); // ❌
</script>Now (auto-imported):
<template>
<div>{{ t("your.translation.key") }}</div>
</template>
<script setup lang="ts">
// No import needed! ✅
</script>Key features:
- No import required
- Auto-completion works in supported IDEs (e.g., VS Code)
- Works in both template and
<script setup>
Translation Key Structure
All translation keys must follow this format:
key.key.key.key.valueRules:
- Keys can have up to 5 levels (e.g.,
checkout.address.form.label) - Every key must have at least one parent (e.g.,
account.nameis valid,nameis not) - Flat keys (single level, like
edit) are not allowed
Examples:
account.settings.profile.editcheckout.address.form.labelproduct.details.price.value
This structure ensures consistency and clarity in all translation files.
Editor Translations
INFO
Important: Editor UI keys (used for the editor interface itself, settings panels, toolbar components, etc.) are not included in the localization editor and are not available for modification by users.
These translations are:
- Isolated from the main translation system
- Stored separately in
apps/web/app/utils/editorTranslations.en.jsonandeditorTranslations.de.json - Managed via the
getEditorUITranslation()andgetEditorTranslation()helper function - Only modifiable by developers through code changes
This separation ensures that the editor interface remains stable and consistent, while giving users full control over their shop's customer-facing content.
Global editor translations vs editor component translations
There are two types of editor translations: We have global editor translations that are used throughout the editor interface (e.g., toolbar messages, common buttons, etc.) and component-specific translations that are only used within a specific component (e.g., settings panels).
Global example
The global function is getEditorUITranslation()
When adding new global editor UI translations (for settings panels, toolbar components, etc.), follow these steps:
Add translation keys to both JSON files:
apps/web/app/utils/editorTranslations.en.jsonapps/web/app/utils/editorTranslations.de.json
Use the
getEditorUITranslation()helper in your components:vue<template> <div>{{ getEditorUITranslation("your-key-name") }}</div> </template>For translations with parameters:
vue<template> <div>{{ getEditorUITranslation("deleteSuccess", { pageName, id }) }}</div> </template>Key structure:
- Use kebab-case for keys (e.g.,
branding-and-design,custom-canonical-URL-for-item-pages) - Keys can be simple strings without dots (unlike the main i18n system)
- Examples:
toolbarSuccess,deleteError,filter.prices.price_asc
- Use kebab-case for keys (e.g.,
Testing:
- Run the test suite to ensure all keys are present in both language files
- Verify parameter placeholders match between languages
- Test:
npm run test apps/web/app/utils/__tests__/editorTranslationsHelper.spec.ts
Component example
Component-specific function is getEditorTranslation() this function has to always be called within the nuxt context!
<template>
<div>{{ getEditorTranslation("component-specific-key") }}</div>
</template>
<script setup lang="ts">
// your code here
</script>
<i18n lang="json">
{
"en": {
"component-specific-key": "Some translation"
},
"de": {
"component-specific-key": "Eine Übersetzung"
}
}
</i18n>WARNING
Because the getEditorTranslation() function uses i18n's t function it needs to be called within the nuxt context, otherwise it will throw an error.
Best practice:
<template>
<div>Hello world</div>
</template>
<script setup lang="ts">
const myFunctionWithIssues = async () => {
const translation = getEditorTranslation("key"); // ❌ will throw error if nuxt context is not available
console.log(translation);
};
const myTranslation = getEditorTranslation("key"); // ✅ safe to use here
const myFunctionSafe = () => {
console.log(myTranslation);
};
</script>
<i18n lang="json">
{
"en": {
"key": "Some translation"
},
"de": {
"key": "Eine Übersetzung"
}
}
</i18n>Migration Guide
Shop version v2.8.0
Starting with shop version v2.8.0 we introduced the new localization editor, in order to be able to translate all keys you need to use our custom auto-imported t function.
Migrating to Auto-Imported t
- Remove any manual imports or injections of
tin your components, example - Use
t('key.path')directly in your templates and scripts - Make sure your IDE is updated for best auto-completion support
Compatibility
Auto-imported t is available in:
- plentyshop-pwa: v2.8.0
- @plentymarkets/shop-core: ^1.14.0
WARNING
⚠️ If you are using an older version, you must continue to import or inject the t function manually.
What Changed in the Editor Translation System
Removed:
- All
lang.jsonfiles from settings folders $registerMessagescalls from View components<i18n>blocks from settings components
Added:
- Two centralized JSON files for all editor UI translations
getEditorUITranslation()helper function replacingt()and$dynamicEditorTranslation()
Benefits:
- Editor translations are completely isolated from customer-facing translations
- No risk of editor UI keys appearing in the localization editor
- Centralized management of all editor UI translations
- Consistent naming and structure across the editor interface
FAQ
Q: Do I need to import t in every file?
A: No.
tis globally available in all Vue components.
Q: Does this work in both <template> and <script setup>?
A: Yes, you can use
tin both places without import.
Q: What if my IDE doesn't autocomplete?
A: Make sure you are using a compatible version and your IDE is up to date.
For more details, contact the core team.
Validation
When adding a new translation file, extend the existing test suite to automatically check that:
- All languages have the same translation keys
- All keys have values in every language