Skip to content

Multi-Language Support

Pest BDD supports writing feature files in over 70 languages. This is powered by the Gherkin parser from Behat, which includes translations for all Gherkin keywords.

Specifying Language

Add a language directive at the top of your feature file:

gherkin
# language: tr
Özellik: Hesap Makinesi
  Temel aritmetik işlemler

  Senaryo: Toplama
    Diyelim ki 5 sayısına sahibim
    Eğer ki 3 eklersem
    O zaman sonuç 8 olmalı

The # language: xx directive tells the parser which language to use for keywords.

Supported Languages

Here are some commonly used languages:

CodeLanguageFeatureScenarioGivenWhenThen
enEnglishFeatureScenarioGivenWhenThen
trTurkishÖzellikSenaryoDiyelim kiEğer kiO zaman
deGermanFunktionalitätSzenarioAngenommenWennDann
frFrenchFonctionnalitéScénarioSoitQuandAlors
esSpanishCaracterísticaEscenarioDadoCuandoEntonces
ptPortugueseFuncionalidadeCenárioDadoQuandoEntão
itItalianFunzionalitàScenarioDatoQuandoAllora
nlDutchFunctionaliteitScenarioGegevenAlsDan
ruRussianФункцияСценарийДопустимКогдаТогда
jaJapaneseフィーチャシナリオ前提もしならば
zh-CNChinese功能场景假如那么
arArabicخاصيةسيناريوبفرضمتىاذاً

For the complete list, see the Gherkin Languages Reference.

Multi-Language Step Definitions

Use repeatable attributes to support the same step in multiple languages:

php
use TestFlowLabs\PestTestAttributes\Given;
use TestFlowLabs\PestTestAttributes\Then;
use TestFlowLabs\PestTestAttributes\When;

class CalculatorSteps
{
    private int $number = 0;

    // English + Turkish
    #[Given('I have number {n}')]
    #[Given('{n} sayısına sahibim')]
    public function haveNumber(int $n): void
    {
        $this->number = $n;
    }

    // English + Turkish
    #[When('I add {n}')]
    #[When('{n} eklersem')]
    public function add(int $n): void
    {
        $this->number += $n;
    }

    // English + Turkish
    #[Then('the result should be {expected}')]
    #[Then('sonuç {expected} olmalı')]
    public function resultShouldBe(int $expected): void
    {
        expect($this->number)->toBe($expected);
    }
}

Now both feature files work:

gherkin
Feature: Calculator
  Scenario: Addition
    Given I have number 5
    When I add 3
    Then the result should be 8
gherkin
# language: tr
Özellik: Hesap Makinesi
  Senaryo: Toplama
    Diyelim ki 5 sayısına sahibim
    Eğer ki 3 eklersem
    O zaman sonuç 8 olmalı

Turkish Example (Complete)

Here's a complete Turkish feature file with all Gherkin keywords:

gherkin
# language: tr
@tarım @kredi
Özellik: Çiftçi Kredi Başvurusu
  Bir çiftçi olarak
  Kredi başvurusu yapmak istiyorum
  Böylece tarımsal yatırımlarımı finanse edebilirim

  Geçmiş:
    Diyelim ki sistem aktif durumda

  @smoke @kritik
  Senaryo: Başarılı kredi başvurusu
    Diyelim ki çiftçi "Ahmet Yılmaz" sisteme kayıtlı
    Ve çiftçinin 50 dönüm arazisi var
    Eğer ki çiftçi 100000 TL kredi başvurusu yaparsa
    O zaman başvuru durumu "onaylandı" olmalı
    Ve çiftçiye bildirim gönderilmeli

  Senaryo: Yetersiz arazi ile başvuru
    Diyelim ki çiftçi "Mehmet Demir" sisteme kayıtlı
    Ve çiftçinin 5 dönüm arazisi var
    Eğer ki çiftçi 100000 TL kredi başvurusu yaparsa
    O zaman başvuru durumu "reddedildi" olmalı
    Fakat çiftçiye red sebebi açıklanmalı

  Senaryo Taslağı: Farklı arazi boyutları
    Diyelim ki çiftçinin <arazi> dönüm arazisi var
    Eğer ki çiftçi <miktar> TL kredi başvurusu yaparsa
    O zaman başvuru durumu "<sonuç>" olmalı

    Örnekler:
      | arazi | miktar | sonuç      |
      | 10    | 50000  | onaylandı  |
      | 50    | 100000 | onaylandı  |
      | 5     | 100000 | reddedildi |

Matching step definitions:

php
class KrediSteps
{
    private ?Farmer $farmer = null;
    private ?Application $application = null;

    #[Given('sistem aktif durumda')]
    public function sistemAktif(): void
    {
        Config::set('loan.system_active', true);
    }

    #[Given('çiftçi {name} sisteme kayıtlı')]
    public function ciftciKayitli(string $name): Farmer
    {
        return $this->farmer = Farmer::factory()->create(['name' => $name]);
    }

    #[Given('çiftçinin {area} dönüm arazisi var')]
    public function ciftcininArazisiVar(int $area): void
    {
        $this->farmer->update(['land_area' => $area]);
    }

    #[When('çiftçi {amount} TL kredi başvurusu yaparsa')]
    public function krediBasvurusu(int $amount): Application
    {
        return $this->application = LoanService::apply(
            $this->farmer,
            $amount
        );
    }

    #[Then('başvuru durumu {status} olmalı')]
    public function basvuruDurumuOlmali(string $status): void
    {
        expect($this->application->status)->toBe($status);
    }
}

German Example

gherkin
# language: de
Funktionalität: Benutzeranmeldung
  Als Benutzer
  Möchte ich mich anmelden können
  Um auf mein Konto zuzugreifen

  Grundlage:
    Angenommen die Anwendung ist gestartet

  Szenario: Erfolgreiche Anmeldung
    Angenommen ein Benutzer "max@example.de" existiert
    Wenn ich mich mit gültigen Anmeldedaten anmelde
    Dann sollte ich das Dashboard sehen

  Szenario: Ungültige Anmeldedaten
    Angenommen ein Benutzer "max@example.de" existiert
    Wenn ich mich mit falschen Anmeldedaten anmelde
    Dann sollte ich eine Fehlermeldung sehen
php
class AnmeldungSteps
{
    #[Given('die Anwendung ist gestartet')]
    #[Given('the application is started')]
    public function appStarted(): void
    {
        // Setup
    }

    #[Given('ein Benutzer {email} existiert')]
    #[Given('a user {email} exists')]
    public function benutzerExistiert(string $email): User
    {
        return User::factory()->create(['email' => $email]);
    }

    #[When('ich mich mit gültigen Anmeldedaten anmelde')]
    #[When('I login with valid credentials')]
    public function gueltigeAnmeldung(): void
    {
        // Login logic
    }

    #[Then('sollte ich das Dashboard sehen')]
    #[Then('I should see the dashboard')]
    public function dashboardSehen(): void
    {
        expect(true)->toBeTrue(); // Assertion
    }
}

Background in Different Languages

The Background keyword has translations in all languages:

LanguageKeyword
EnglishBackground
TurkishGeçmiş
GermanGrundlage
FrenchContexte
SpanishAntecedentes
PortugueseContexto
ItalianContesto

And/But Conjunctions

Conjunction keywords are also translated:

LanguageAndBut
EnglishAndBut
TurkishVeFakat
GermanUndAber
FrenchEtMais
SpanishYPero

Example in Turkish:

gherkin
# language: tr
Senaryo: Detaylı test
  Diyelim ki kullanıcı mevcut
  Ve kullanıcı admin
  Eğer ki giriş yaparsam
  O zaman dashboard görmeliyim
  Fakat ayarları görmemeli

Best Practices

Choose One Primary Language

For consistency, pick one primary language for your project:

gherkin
# All features in Turkish
# language: tr
Özellik: ...

Support Both Languages in Steps

When collaborating internationally, support multiple languages:

php
// Support both English and local language
#[Given('a user exists')]
#[Given('bir kullanıcı mevcut')]
public function userExists(): User
{
    return User::factory()->create();
}

Document Language Choice

Add to your README or contributing guide:

markdown
## BDD Language

Feature files are written in Turkish (`# language: tr`).
Step definitions support both Turkish and English patterns.

Use UTF-8 Encoding

Ensure your feature files are saved with UTF-8 encoding to support non-ASCII characters:

php
// In tests or configuration
mb_internal_encoding('UTF-8');

IDE Support

Most IDEs with Gherkin support handle multi-language files:

  • PHPStorm: Full Gherkin support with language detection
  • VS Code: Cucumber/Gherkin extension with language support
  • Sublime Text: Gherkin syntax highlighting packages

Released under the MIT License.