Windwalker use Language package to handle i18n localise. There is a language configuration in /etc/config.yml:

    debug: 0
    locale: zh-TW
    default: en-GB
    format: ini
    path: resources/languages

locale means current language, and default will tell language object that if current translate not exists, fallback to which language as default.

Format is the default file format, but we can still load other format in the runtime.

Using Language to Translate String

Windwalker language object has a Facade as proxy, just call this static class to use.

use Windwalker\Core\Language\Translator;

// Load en-GB/main.ini file first

// Translate
echo Translator::translate('windwalker.hello.message');

Add language:

; resources/languages/en-GB/main.ini

windwalker.hello.message="Hello World"

The result will be:

Hello World

There is a short alias of translate():

echo Translator::translate('windwalker.hello.message');

Locale and Default Languages

We set locale to zh-TW and default to en-GB, then create ini language files:

; resources/languages/en-GB/flower.ini

; resources/languages/zh-TW/flower.ini


And load them.


Translate string:

// zh-TW has this language key, so it will be translated
Translator::translate('windwalker.language.test.flower'); // 花

// This key not exists in zh-TW, use en-GB as default
Translator::translate(''); // Sakura

Key Format

All language key will be normalised to lowercase and separated by dot (.).

These cases all get same result:

Translator::translate('WINDWALKER_LANGUAGE_TEST_FLOWER'); // 花
Translator::translate('WINDWALKER_language_TEST FLOWER'); // 花
Translator::translate('windwalker.language.test.flower'); // 花
Translator::translate('Windwalker Language Test Flower'); // 花
Translator::translate('Windwalker Language, Test Flower~~~!'); // 花

// All keys will be normalise to 'windwalker.language.test.flower'

Replace String

Use sprintf() method.

windwalker.language.test.beautiful.flower="The %s is beautiful~~~!!!"
Translator::sprintf('windwalker.language.test.beautiful.flower', 'Sunflower');

// Result: The Sunflower is beautiful~~~!!!

Plural String

Create a Localise class:

// An example of EnGB Localise
namespace Windwalker\Language\Localise;

class EnGBLocalise implements LocaliseInterface
    public function getPluralSuffix($count = 1)
        if ($count == 0)
            return '0';
        elseif ($count == 1)
            return '';

        return 'more';

And prepare this language keys.

windwalker.language.test.sunflower="No Sunflower"

Now we can translate plural string by plural().

Translator::plural('windwalker.language.test.sunflower', 0); // No Sunflower
Translator::plural('windwalker.language.test.sunflower', 1); // Sunflower
Translator::plural('windwalker.language.test.sunflower', 2); // Sunflowers

If Language Key Not Exists

Language object will return raw string which we send into it.

echo Translator::translate('A Not Translated String');
echo "\n";
echo Translator::translate('A_NOT_TRANSLATED_STRING');


A Not Translated String

Using Other Formats

Change the format property from config.


Yaml language file can write as nested structure.

        sakura: Sakura
        olive: Olive
Translator::translate(''); // Sakura
Translator::translate('WINDWALKER_LANGUAGE_TEST_OLIVE'); // Olive


    "windwalker" : {
        "language-test" : {
            "sakura" : "Sakura",
            "olive" : "Olive"

The usage same as yaml.

Translator::translate(''); // Sakura
Translator::translate('WINDWALKER_LANGUAGE_TEST_OLIVE'); // Olive



return array(
            'TEST' => array(
                'SAKURA' => "Sakura"

The usage same as yaml.

Translator::translate(''); // Sakura
Translator::translate('WINDWALKER_LANGUAGE_TEST_OLIVE'); // Olive

NOTE: We'll support to load different formats in the runtime soon.

Load Package Languages

Package language file located at YourPackage/Languages/xx-XX/language-name.ini.

So we can load package languages by second argument:

// Load en-GB/sakura.ini and zh-TW/sakura.ini from Flower package
Translator::loadFile('sakura', 'ini', 'flower');

Used Keys

// Get keys which have been used.


Debug Mode


We can get non-translated keys in debug mode.

echo Translator::translate('A Translation Exists String');
echo "\n";
echo Translator::translate('A Not Translated String');

And the output will be:

**A Translation Exists String**
??A Not Translated String??

Get Orphans

Orphans is the language string you used but haven't translated.


// Run your applications

$orphans = Translator::getOrphans(); // Array([0] => A Not Translated String);

Check Loaded Languages

$config = \Windwalker\Ioc::getConfig();


Translate in View Template


@sprintf('windwalker.language.test.flower', 'foo', 'bar')
@plural('windwalker.language.test.flower', 5)


{{ 'windwalker.language.test.flower' | lang }}
{{ 'windwalker.language.test.flower' | sprintf('foo', 'bar') }}
{{ 'windwalker.language.test.flower' | plural(5) }}

If you found a typo or error, please help us improve this document.