Skip to content
Matheus Clemente edited this page Oct 11, 2023 · 10 revisions

Audience: This paragraph is intended for module and system developers that want to add more complex behavior to Polyglot. If you just want to use this addon's features, skip this paragraph.

You can add your own set of alphabets and languages to Polyglot to a system, along with the logic to check for user languages. Doing so is simple. This paragraph will provide an example by showing an implementation of the api for a fictional game system, that contains everything you need to get started. Afterwards the code will be dissected into small parts and explained.

Full Example
Hooks.once("polyglot.init", (LanguageProvider) => {
    class FictionalGameSystemLanguageProvider extends LanguageProvider {
              languages = {
            common: {
                  label: "Common",
                  font: "Thorass",
                  rng: "default",
            },
            dwarvish: {
                  label: "Dwarvish",
                  font: "Dethek",
                  rng: "default",
            },
            elvish: {
                  label: "Elvish",
                  font: "Espruar",
                  rng: "default"
            },
            orcish: {
                  label: "Orcish",
                  font: "Dethek",
                  rng: "default",
            },
      }
		
	async getLanguages() {
		const langs = {};
		if (this.replaceLanguages) {
			CONFIG.FICTIONAL.spoken = {};
		}
		const languagesSetting = game.settings.get("polyglot", "Languages");
		for (let lang in CONFIG.FICTIONAL.spoken) {
			langs[lang] = {
				label: CONFIG.FICTIONAL.spoken[lang],
				font: languagesSetting[lang]?.font || this.languages[lang]?.font || this.defaultFont,
				rng: languagesSetting[lang]?.rng ?? "default",
			};
		}
		this.languages = langs;
	}
		
        getUserLanguages(actor) {
            let known_languages = new Set();
            let literate_languages = new Set();
            for (let lang of actor.system.attributes.languages.value) {
                known_languages.add(lang)
			}
            return [known_languages, literate_languages];
        }
    }
    game.polyglot.api.registerModule("my-module-id", FictionalGameSystemLanguageProvider);
    // game.polyglot.api.registerSystem(FictionalGameSystemLanguageProvider);
})

Explanation of the code

Hooks.once("polyglot.init", (LanguageProvider) => {
    class FictionalGameSystemLanguageProvider extends LanguageProvider {

Initialization

After Polyglot's API has been initialized, it will fire the polyglot.init event. This is the signal for your module/gamesystem that it can now register itself in Polyglot. To do this you'll need to implement a Language Provider. The Hook will provide you with one Argument: The class LanguageProvider, which serves as base class for all language providers.

Implementation

To implement a Language Provider you create a subclass of LanguageProvider. Within that class you override functions of the base class to implement the functionality you need.

You probably will need to set your own languages property, with values for label and font ("rng" is optional). You can set languages without a proper label and have the getLanguages method set the labels later (for example, for localized language names, since you can't call game.i18n.localize on a property).

Of all the systems Polyglot supports, only one doesn't implement a languages property because the system has its own setting to add languages.

You probably will need to override getLanguages and getUserLanguages methods to accomodate them for the specifics of your system.

      languages = {
            common: {
                  label: "Common",
                  font: "Thorass",
                  rng: "default",
            },
            dwarvish: {
                  label: "Dwarvish",
                  font: "Dethek",
                  rng: "default",
            },
            elvish: {
                  label: "Elvish",
                  font: "Espruar",
                  rng: "default"
            },
            orcish: {
                  label: "Orcish",
                  font: "Dethek",
                  rng: "default",
            },
      }

The languages property has a list of the languages implemented,.

  • label is a language's name that is shown to users.
  • font is a font previously set on LanguageProvider.fonts.
  • rng defines randomization used for the language. The other options are unique (strings are always unique) and none (strings are never randomized).
		async getLanguages() {
			const langs = {};
			if (this.replaceLanguages) {
				CONFIG.FICTIONAL.languages = {};
			}
			const languagesSetting = game.settings.get("polyglot", "Languages");
			for (let lang in CONFIG.FICTIONAL.languages) {
				langs[lang] = {
					label: CONFIG.FICTIONAL.languages[lang],
					font: languagesSetting[lang]?.font || this.languages[lang]?.font || this.defaultFont,
					rng: languagesSetting[lang]?.rng ?? "default",
				};
			}
			this.languages = langs;
		}

The getLanguages method is meant to set the label and rng for the languages in a way that the user can change them later. So you should always check for Polyglot's "Languages" setting first like this.

        getUserLanguages(actor) {
            let known_languages = new Set();
            let literate_languages = new Set();
            for (let lang of actor.system.attributes.languages.value) {
				known_languages.add(lang)
			}
            return [known_languages, literate_languages];
        }

The getUserLanguages method defines the logic to check for an actor's known languages. Its implementation varies from system to system due to where the languages data is set on the template structure.

  • known_languages: The languages that are known by the actor.
  • literate_languages: Optional variable to be used for systems where literacy isn't tied to being able to speak the language.
   game.polyglot.api.registerModule("my-module-id", FictionalGameSystemLanguageProvider)
   // game.polyglot.api.registerSystem(FictionalGameSystemLanguageProvider);
})

This line registers the Language Provider class that was just created with Polyglot. The paramater must be the id of the module you're writing. This id must exactly match the id specified in you manifest. As the second parameter the Language Provider class that was just created is passed in.

If you're not writing to a game system instead, use the game.polyglot.api.registerSystem commented line instead, which doesn't take the system's id as a parameter.

Additional capabilities of the API

In addition to the basic capabilities of the API presented in the example above, Polyglot's API offers more capabilities. To learn more about additional capabilities refer to the documentation of the Language base class in LanguageProvider.js.

Clone this wiki locally