Dictionaries

Dictionaries are also a core of the GM-I18n system. They are used to translating your messages furtherly, so your message will appear in very natural way.

Do I need to use dictionaries?

Let's see the example below first before you answer.

Create Event
// assume you've initialized the i18n system

text = i18n_create_ref_message("text", "ask", {     // create message ref with "ask" key
    item: "apple"                                   // and pass the required data
});
Key Pressed - Space
// change the locale

switch (i18n_get_locale()) {
    case "en": i18n_set_locale("id"); break;
    case "id": i18n_set_locale("ja"); break;
    case "ja": i18n_set_locale("en"); break;
}
en.json
{
    "ask": "Do you want this {item}?"
}
id.json
{
    "ask": "Apakah kamu ingin {item} ini?"
}
ja.json
{
    "ask": "この{item}が欲しいですか?"
}

The expected result is:

  • en : Do you want this apple?
  • id : Apakah kamu ingin apple ini?
  • ja : このappleが欲しいですか?

Well, how do you think? The interpolation works, but it's not natural, right? The apple is not translated, it's just passed as it is. That's where dictionaries come in!

You can now answer the previous question, do I need to use dictionaries?


How It Works

Here's a simple example of how dictionaries work:

  1. Get a message using i18n_get_messages(), or create a message reference using i18n_create_ref_message().
  2. Pass the data on the message or message reference. In the example above, we pass the item data.
  3. The system checks if the item data value (apple) is registered in the dictionary of the used locale.
  4. If it is, the system will use the dictionary value instead of the data value. If it's not, the system will use the data value as is.

Registering Dictionaries

You can register dictionaries using the i18n_add_dictionaries() function. It's similar to i18n_add_messages(), but it's only accepts data in array format, where each item is a pair of key and value, like ["key", "value"].

You can also register multiple dictionaries at once by passing an array of pairs, like ["key1", "value1"], ["key2", "value2"].

Functions

i18n_add_dictionaries

Syntax
i18n_add_dictionaries(locale, data, [i18n]);
Description

Adds dictionaries to the specified locale.

Parameters
NameTypeDefaultDescription
localeStringThe locale to add the dictionaries to.
data[String, String] | [String, String][]The dictionaries to add with ["key", value] pair, or array of ["key", value] pair.
i18nBoolean | I18nfalseThe I18n struct reference, or leave it empty to use the global i18n struct.
Returns

Void

Examples
Create Event
// add "apple" -> "apel" dictionary to "id" locale
i18n_add_dictionaries("id", ["apple", "apel"]);

// add more dictionaries to "id" locale
i18n_add_dictionaries("id", [
    ["banana", "pisang"],
    ["orange", "jeruk"],
    ["one", "satu"],
    ["two", "dua"],
    ["three", "tiga"]
]);

// add dictionaries to "ja" locale
i18n_add_dictionaries("ja", [
    ["apple", "リンゴ"],
    ["banana", "バナナ"],
    ["orange", "オレンジ"],
    ["one", "一"],
    ["two", "二"],
    ["three", "三"]
]);

// you can add number as well
i18n_add_dictionaries("ar", [
    ["1", "١"],
    ["2", "٢"],
    ["3", "٣"],
    ["4", "٤"],
    ["5", "٥"]
]);

// you can also add dictionaries for the default locale (en), or variant of it
i18n_add_dictionaries("en_GB", [
    ["soccer", "football"],
    ["cookie", "biscuit"],
    ["fries", "chips"]
])

// key-value pair is also supported
i18n_add_dictionaries("en", [
    ["hello", "Hello World!"],
    ["btn.cancel", "Cancel"],
    ["btn.yes", "Yes"],
    ["btn.no", "No"]
]);

// you can make it as a glossary-like dictionaries
i18n_add_dictionaries("en", [
    ["Cure", "A beginner skill of a healer that heals a single target."],
    ["Will of the Adventurer", "A skill that increases the user's attack power by 10% for 30 seconds."],
    ["Fireball", "A powerful fire spell that deals damage to all enemies in a small area."],
    ["Potion", "A consumable item that restores 50 HP when used."],
    ["Elixir", "A consumable item that restores 100 MP when used."],
    ["Mana Potion", "A consumable item that restores 50 MP when used."],
    ["Phoenix Down", "An item that revives a fallen ally with 50% HP."],
    ["Ether", "An item that restores 30 MP to an ally."]
]);
You normally register dictionaries for other locales than the default locale (in this case, en), so you can use the i18n_add_dictionaries() function to register dictionaries for id and ja locales as shown in the example above.

You can also register dictionaries for the default locale. Maybe, you want to override the default dictionary value for some reason.
If you register a dictionary with the same key as an existing one, it will override the existing value. So, be careful when registering dictionaries.

The key is case-sensitive, so apple and Apple are considered different keys. It also only accept String as the key.

Using Dictionaries

The dictionaries won't be used automatically. You need to add $ prefix to the named data in the message reference or message, like ${item}. The system will then check if the value of {item} is registered in the dictionaries of the current locale. If it is, the system will use the dictionary value instead of the data value.

Format: ${data_name}
Placeholder: ${data_name1}, ${data_name2}, etc.
Used In: [locale].json

Here's an example of how to use it:

Create Event
// assume you've initialized the i18n system

// add the required dictionaries
i18n_add_dictionaries("en", [
    ["item.map", "Village Map"],
    ["apple_box", "box of apples"],
    ["Will of the Adventurer", "A skill that increases the user's attack power by 10% for 30 seconds"]
]);

i18n_add_dictionaries("id", [
    ["ticket", "tiket"],
    ["apple", "apel"],
    ["item.map", "Peta Desa"],
    ["apple_box", "kotak apel"],
    ["Will of the Adventurer", "Keterampilan yang meningkatkan kekuatan serangan pengguna sebesar 10% selama 30 detik"]
]);

i18n_add_dictionaries("ja", [
    ["ticket", "チケット"],
    ["apple", "リンゴ"],
    ["item.map", "村の地図"],
    ["apple_box", "リンゴの箱"],
    ["Will of the Adventurer", "ユーザーの攻撃力を30秒間10%上昇させるスキル"]
]);


// on static message
ask1 = i18n_get_messages("ask", {       // "ask" key
    item: "apple"                       // pass the required data without dictionary
}, "id");                               // "Apakah kamu ingin apple ini?" ("apple" is not translated)

ask2 = i18n_get_messages("ask_2", {     // "ask_2" key
    item: "apple"                       // pass the required data with dictionary (add `$` prefix before the data name)
}, "id");                               // "Apakah kamu ingin apel ini?" (natural translation)
                                        // "apple" -> "apel" (from "id" dictionary)

player_name = "John";

// on message reference
npc1 = i18n_create_ref_message("npc1", "dialog.npc_1", {
    chief_name : "Budi"                 // "Budi" is not registered in any dictionary
});                                     // so, it will be used as is (chief_name: "Budi")
                                        // `en` : "Please ask Budi for help."

my_struct = {
    npc2 : i18n_create_ref_message("my_struct.npc2", "dialog.npc_2", {
        name : player_name,
        item : "item.map"               // using dictionary for "item.map"
    })                                  // `en` : "Is it your first time here, John? Let me show you around. Here's a Village Map for you."
};

global.npc3 = i18n_create_ref_message("global.npc3", "dialog.npc_3", {
    plural : function(val) {            // with pluralization            
        return (val >= 3) ? 1 : 0;      // if `plural_value` is 3 or more, use pluralization form 2 (index 1), otherwise use pluralization form 1 (index 0)
    },
    plural_value : 0,                   // this will be used to determine the pluralization form

    item : "ticket",                    // using dictionary for "ticket"
    count : 3,
    suffix : "s"
});                                     // `en` : "You need at least 3 tickets to enter the cave." (if `plural_value` is lower than 3)
                                        // `en` : "Spend {plural_value} tickets to enter the cave?" (if `plural_value` is 3 or more, interpolation will be used)

global.gb_struct = {
    // using linked message
    npc4 : i18n_create_ref_message("g.gb_struct.npc4", "dialog.npc_4", {
        child : {                       // data for the child message
            sp_item : "apple_box"       // using dictionary for "apple_box"
        }                               // `en` : "My brother was trapped in the cave. I need to find him. Can you help me? I'll reward you with a box of apples if you can find him."
    }),

    arr : [
        // a direct example to distinguish between normal named data and dictionary
        // see the `item` placeholder in the message
        i18n_create_ref_message("global.gb_struct.arr.0", "dialog.npc_6", {
            item : "Will of the Adventurer"     // using dictionary for "Will of the Adventurer"
        })                                      // `en` : "Take this "Will of the Adventurer" skill book. It's A skill that increases the user's attack power by 10% for 30 seconds."
    ]
}
en.json
{
    "greet": "Hello, {name}!",
    "ask": "Do you want this {item}?",
    "ask_2": "Do you want this ${item}?",
    "dialog": {
        "npc_1": "Please ask ${chief_name} for help.",
        "npc_2": "Is it your first time here, {name}? Let me show you around. Here's a ${item} for you.",
        "npc_3": "You need at least {count} ${item}{suffix} to enter the cave. | Spend {plural_value} ${item}{suffix} to enter the cave?",
        "npc_4": "My brother was trapped in the cave. I need to find him. Can you help me? [[dialog.npc_5]]",
        "npc_5": "I'll reward you with a ${sp_item} if you can find him.",
        "npc_6": "Take this \"{item}\" skill book. It's ${item}."
    }
}
id.json
{
    "greet": "Halo, {name}!",
    "ask": "Apakah kamu ingin {item} ini?",
    "ask_2": "Apakah kamu ingin ${item} ini?",
    "dialog": {
        "npc_1": "Harap tanyakan bantuan kepada ${chief_name}.",
        "npc_2": "Ini pertama kalinya kamu di sini, {name}? Mari saya tunjukkan sekeliling. Ini ${item} untukmu.",
        "npc_3": "Kamu butuh setidaknya {count} ${item} untuk masuk ke gua. | Habiskan {plural_value} ${item} untuk masuk ke gua?",
        "npc_4": "Saudaraku terjebak di dalam gua. Aku perlu menemukannya. Bisakah kamu membantuku? [[dialog.npc_5]]",
        "npc_5": "Aku akan memberimu ${sp_item} jika kamu bisa menemukannya.",
        "npc_6": "Ambil buku keterampilan \"{item}\" ini. Ini ${item}."
    }
}
ja.json
{
    "greet": "こんにちは、{name}さん!",
    "ask": "この{item}が欲しいですか?",
    "ask_2": "この${item}が欲しいですか?",
    "dialog": {
        "npc_1": "${chief_name}さんに助けを求めてください。",
        "npc_2": "{name}さん、初めてここに来たのですか?周りを案内しましょう。これはあなたへの${item}です。",
        "npc_3": "洞窟に入るには少なくとも{count}個の${item}が必要です。| 洞窟に入るために{plural_value}個の${item}を使いますか?",
        "npc_4": "私の兄が洞窟に閉じ込められています。彼を見つける手伝いをしてくれませんか?[[dialog.npc_5]]",
        "npc_5": "${sp_item}を見つけたら報酬をあげますよ。",
        "npc_6": "\"{item}\"スキルブックを受け取ってください。これは${item}です。"
    }
}
You can use the i18n_get_messages() or i18n_create_ref_message() function to get a message or create a message reference with the data that contains the dictionary value. The system will automatically use the dictionary value if it exists, or the data value as is if it doesn't.

As you can see in the example above, the value of the passed data become the key of the dictionary, and the key of the message is used as the value of the dictionary. For example, the item data in the ask_2 message has the value of apple, which is registered in the id locale dictionary as apel. So, the system will use the apel value instead of apple when rendering the message.
You can't use dictionaries in an indexed data interpolation, like {0}, {1}, etc. Dictionaries only work with named data interpolation, like {item} or {name}.

The dictionaries are used only if you use the $ prefix on the data name in the message or message reference. If you don't use the $ prefix, the system will use the data value as is, without checking the dictionaries.

If you use the $ prefix, but the value is not registered in the dictionaries, the system will use the data value as is.

  It's a good practice to use dictionaries for any data that you want to translate, especially for items, skills, and other game-related terms. This way, you can easily manage the translations and make sure they are consistent across your game.