Skip to content

Language Agnostic Testing ​

Language agnostic testing in @shopware-ag/acceptance-test-suite allows you to write acceptance tests that work across different languages without hard-coding text strings. Tests use translation keys instead of hard-coded strings and automatically adapt to different locales via environment variables.

translate() Function ​

Use the translate() function in page objects to replace hardcoded strings with translation keys.

Usage in Page Objects ​

typescript
import { translate } from '../../services/LanguageHelper';

export class CategoryListing implements PageObject {
    constructor(page: Page) {
        this.createButton = page.getByRole('button', {
            name: translate('administration:category:actions.createCategory'),
        });
    }
}

Translate Fixture ​

The Translate fixture provides translation functionality in tests.

Usage in Tests ​

typescript
import { test, expect } from '@shopware-ag/acceptance-test-suite';

test('Category creation', async ({ AdminPage, Translate }) => {
    const saveText = Translate('administration:category:general.save');
    await AdminPage.getByRole('button', { name: saveText }).click();
});

Environment Control ​

Switch test language using environment variables:

bash
LANG=de-DE npm run test  # German
LANG=en-GB npm run test  # English (default)

Translation Keys ​

Translation keys follow the pattern: area:module:section.key

Examples ​

typescript
'administration:category:general.save';
'administration:category:actions.createCategory';
'storefront:account:fields.firstName';
'storefront:checkout:payment.invoice';

Locale Files ​

Translations are stored in JSON files organized by language and area:

  • locales/en/administration/category.json
  • locales/de/administration/category.json
  • locales/en/storefront/account.json
  • locales/de/storefront/account.json

Example Translation Files ​

English (locales/en/administration/category.json):

json
{
    "general": {
        "save": "Save",
        "cancel": "Cancel"
    },
    "actions": {
        "createCategory": "Create category"
    }
}

German (locales/de/administration/category.json):

json
{
    "general": {
        "save": "Speichern",
        "cancel": "Abbrechen"
    },
    "actions": {
        "createCategory": "Kategorie erstellen"
    }
}

Supported Locales ​

Translation Resources: en (English), de (German)
Browser UI: en, de, fr, es, it, nl, pt

Common Issues ​

Translation key not found:

  • Verify key exists in both EN/DE locale files
  • Check import in locales/index.ts
  • Ensure proper namespace structure

Tests fail with LANG changes:

  • Move translate() calls inside constructors/functions, not at module level
  • Ensure translation resources are properly loaded

JSON import errors:

  • Always use with { type: 'json' } import attribute
  • Check file paths and naming conventions

Browser locale not matching:

  • Verify locale mapping in playwright.config.ts
  • Check browser args configuration
  • Ensure language detection is working correctly

Using in Your Own Project ​

If you want to use the @shopware-ag/acceptance-test-suite in your own project with custom translations, you can extend the base test suite with your own translation fixture.

Installation ​

First, install the required dependencies:

bash
npm install @shopware-ag/acceptance-test-suite @playwright/test
npm install -D @types/node

Create Custom Translation Fixture ​

Create a new fixture file (e.g., fixtures/CustomTranslation.ts):

typescript
import {
    test as base,
    LanguageHelper,
    TranslationKey,
    TranslateFn,
    BUNDLED_RESOURCES,
    baseNamespaces,
} from '@shopware-ag/acceptance-test-suite';
import { LOCALE_RESOURCES, enNamespaces } from '../locales';

// Merge base BUNDLED_RESOURCES with your custom LOCALE_RESOURCES
const MERGED_RESOURCES = {
    en: { ...BUNDLED_RESOURCES.en, ...LOCALE_RESOURCES.en },
    de: { ...BUNDLED_RESOURCES.de, ...LOCALE_RESOURCES.de },
} as const;

// Merge base and custom namespaces
const mergedNamespaces = {
    ...baseNamespaces,
    ...enNamespaces,
} as const;

type CustomTranslationKey = TranslationKey<typeof mergedNamespaces>;

interface CustomTranslateFixture {
    Translate: TranslateFn<CustomTranslationKey>;
}

export const test = base.extend<CustomTranslateFixture>({
    Translate: async ({}, use) => {
        let lang = process.env.lang || process.env.LANGUAGE || process.env.LANG || 'en';
        let language = lang.split(/[_.-]/)[0].toLowerCase();

        if (!MERGED_RESOURCES[language as keyof typeof MERGED_RESOURCES]) {
            console.warn(
                `⚠️  Translation resources for '${language}' not available. Supported: ${Object.keys(
                    MERGED_RESOURCES
                ).join(', ')}. Falling back to 'en'.`
            );
            language = 'en';
        }

        const languageHelper = await LanguageHelper.createInstance(
            language,
            MERGED_RESOURCES as unknown as typeof BUNDLED_RESOURCES
        );

        const translate: TranslateFn<CustomTranslationKey> = (key, options) => {
            return languageHelper.translate(key as TranslationKey, options);
        };

        await use(translate);
    },
});

export * from '@shopware-ag/acceptance-test-suite';
export type { CustomTranslationKey };

Create Locale Files Structure ​

Organize your translation files by language and area:

text
project-root/
├── locales/
│   ├── en/
│   │   ├── administration/
│   │   │   ├── common.json
│   │   │   └── product.json
│   │   └── storefront/
│   │       ├── account.json
│   │       └── checkout.json
│   ├── de/
│   │   ├── administration/
│   │   │   ├── common.json
│   │   │   └── product.json
│   │   └── storefront/
│   │       ├── account.json
│   │       └── checkout.json
│   └── index.ts
├── fixtures/
│   └── CustomTranslation.ts
├── types/
│   └── TranslationTypes.ts
└── tests/
    └── your-test.spec.ts

Create Locales Index ​

Create locales/index.ts to import and export your translation files:

typescript
// Import all locale files
import enAdministrationCommon from './en/administration/common.json' with { type: 'json' };
import enStorefrontAccount from './en/storefront/account.json' with { type: 'json' };

import deAdministrationCommon from './de/administration/common.json' with { type: 'json' };
import deStorefrontAccount from './de/storefront/account.json' with { type: 'json' };

// Export the bundled resources for i18next
export const LOCALE_RESOURCES = {
    en: {
        'administration/common': enAdministrationCommon,
        'storefront/account': enStorefrontAccount,
    },
    de: {
        'administration/common': deAdministrationCommon,
        'storefront/account': deStorefrontAccount,
    },
} as const;

export const enNamespaces = {
    administration: {
        common: enAdministrationCommon,
    },
    storefront: {
        account: enStorefrontAccount,
    },
} as const;

Create Translation Types ​

Create types/TranslationTypes.ts to define your custom translation types. This provides:

  • Type Safety: Ensures translation keys exist in your locale files
  • IntelliSense: Auto-completion for available translation keys
  • Compile-time Validation: Catches typos and missing keys before runtime
typescript
import { TranslationKey, TranslateFn } from '@shopware-ag/acceptance-test-suite';
import { enNamespaces } from '../locales';

export type CustomTranslationKey = TranslationKey<typeof enNamespaces>;

export type CustomTranslateFn = TranslateFn<CustomTranslationKey>;

Merge with Base Test Suite ​

Create your main test fixture that merges the base test suite with your custom translation:

typescript
import { test as ShopwareTestSuite, mergeTests } from '@shopware-ag/acceptance-test-suite';
import { test as CustomTranslation } from './fixtures/CustomTranslation';

export * from '@shopware-ag/acceptance-test-suite';

export const test = mergeTests(ShopwareTestSuite, CustomTranslation);

Note: Save this as test.ts or index.ts in your project root and import it in your test files.

Usage in Your Tests ​

Now you can use the Translate fixture in your tests:

typescript
import { test } from './your-main-test-fixture';

test('My localized test', async ({ Translate, AdminPage }) => {
    const saveText = Translate('administration:common:button.save');
    await AdminPage.getByRole('button', { name: saveText }).click();
});

Environment Configuration ​

Set up your Playwright configuration to support language switching:

typescript
// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

const LOCALES = { de: 'de-DE', en: 'en-US', fr: 'fr-FR' };

function getLanguage(): string {
    let lang = process.env.lang || process.env.LANGUAGE || process.env.LANG || 'en';
    return lang.split(/[_.-]/)[0].toLowerCase();
}

function getLocaleConfig() {
    const lang = getLanguage();
    const browserLocale = LOCALES[lang as keyof typeof LOCALES] || 'en-US';
    const browserArgs =
        lang !== 'en' && LOCALES[lang as keyof typeof LOCALES]
            ? [`--lang=${browserLocale}`, `--accept-lang=${browserLocale},${lang};q=0.9,en;q=0.8`]
            : [];

    return { lang, browserLocale, browserArgs };
}

export default defineConfig({
    use: {
        locale: getLocaleConfig().browserLocale,
    },
    projects: [
        {
            name: 'Platform',
            use: {
                ...devices['Desktop Chrome'],
                launchOptions: {
                    args: [...getLocaleConfig().browserArgs],
                },
            },
        },
    ],
});

Running Tests with Different Languages ​

bash
# German
LANG=de-DE npx playwright test

# English (default)
npx playwright test
Was this page helpful?
UnsatisfiedSatisfied
Be the first to vote!
0.0 / 5  (0 votes)