---
title: "🔣 Локализация в GameMaker"
date: 2023-01-09T01:53:00+03:00
draft: false
tags: [tutorial, gamemaker, gamedev]
---

## Много игроков = много языков

Вполне нормальное явление, когда игра поддерживает несколько языков.  
В этом руководстве я покажу, как можно реализовать локализацию в GameMaker.

## Установка языка игры

Чаще всего в играх разработчик делает отдельное меню
или селектор в настроках для смены языка.

И это хороший подход, так как зачастую перевод игры на родной язык хромает.  
Бывает, да 😑

В данном руководстве я буду получать язык системы игрока динамически,
но ничего не мешает тебе внести насколько правом, чтобы сделать изменение языка
из меню настроек.

В GameMaker есть функция `os_get_language()`, которая возвращает строку с двухбуквенным кодом языка операционной системы на которой запущена игра. Возвращаемое значение соотвествует стандарту
[ISO639](https://ru.wikipedia.org/wiki/ISO_639).

В таблице ниже приведены примеры некоторых двухбуквенных кодов языков, определенных стандартом ISO 639:

```text
| Язык            | Код |
|-----------------|-----|
| Английский язык |  en |
| Русский язык    |  ru |
| Немецкий язык   |  de |
| Японский язык   |  ja |
```

## Получение значений

Я написал функцию `get_l10n_text()`, которая принимает текстовое значение,
ищет его в массиве строк и возвращает значение в соответствии с установленным в ОС языком.

Полный код функции:

```cpp
function get_l10n_text(text) {
    var strings = {
        locales: ["en", "ru"],
        reset_btn: {
            desc: "The restart button in menu",
            en: "Restart",
            ru: "Играть снова"
        },
        start_btn: { desc: "The start button in menu", en: "Start", ru: "Играть" }
    };

    var lng = os_get_language();

    if (!array_has(strings.locales, lng)) { lng = "en"; }

    var text_struct = variable_struct_get(strings, text);

    return variable_struct_get(text_struct, lng);
}
```

## Разбор кода

Структура `strings` хранит в себе строки с их переводами а другие языки.

Например `reset_btn` это кнопка сброса в игре. В коде я вызываю функцию `get_l10n_text()`
используя в качестве аргумента это значение.

Значения `en` и `ru` соответствуют переведённым строкам.  
Значение `desc` используется для описания.

Первый делом я присваиваю переменной `lng` значение языка установленного в ОС
и проверяю, имеется ли перевод для этого языка.  
Если перевода нет, использую язык по умолчанию.

```cpp
var lng = os_get_language();
if (!array_has(strings.locales, lng)) { lng = "en"; }
```

В выражении `if` я использую функцию `array_has()`, которая принимает
в качестве первого агрумента структуру, а в качестве второго аргумента
значение, которое необходимо в ней найти.

Код функции `array_has()`:

```cpp
function array_has(array_to_search, value_to_find) {
    var search_array = array_to_search;
    var find_value = value_to_find;
    var loop = 0;
    repeat (array_length_1d(search_array)) if (search_array[loop++] == find_value) return true;
    return false;
}
```

Далее я получаю значение из структуры и возвращаю его.

```cpp
var text_struct = variable_struct_get(strings, text);
return variable_struct_get(text_struct, lng);
```
