Iavra Game Localization - Core Engine, Database, Messages

Iavra

Veteran
Veteran
Joined
Apr 9, 2015
Messages
1,797
Reaction score
866
First Language
German
Primarily Uses
Description

Allows to store all text content of your game in external files. Persists the current language in its own file and allows language switching at runtime.

Prerequisites

The Core engine is needed for the individual modules to work. Optionally, my Game.ini Acces script (Link) can be used to save the current language inside the Game.ini.

Features

Allows to load the text content of your game from external files and switch between multiple languages at runtime. The script is split into 3 parts: The Core engine, the Database module and the Messages module. Both modules need the engine to function, but can be used independently from each other.

The different features of the scripts are:

Core

- Loading of external text files from a configurable part.

- Possibility of splitting the data into multiple files, even withing categories with an optional DEEP_MERGE functionality.

- Option to evaluate the loaded data inside a seperate thread with $SAFE = 4, which acts as a sandbox.

- The current language can be stored inside its own file or inside the Game.ini by using another of my scripts.

- Extendable update method, which is called every time the current language is changed.

Database

- Localization of database entries, which include: Actors, Classes, Skils, Items, Weapons, Armors, Enemies, States, System, Terms, Vocab and Map names.

- Optional CLEAN_ACTORS mode, which removes the only trace of the script prior to saving, so it can be removed without having to start a new game.

- Older savegames will also be localized, making the script completely plug-and-play.

- Falls back to the default value (as given in the editor) if an attribute isn't provided in the language files.

Messages

- Introduces a new, configurable message code, which will be replaced with localized text loaded with the core engine.

- All basic message codes also work inside dynamically loaded text (though you need to double the backslashes, for example \\v[1] instead of \v[1]).

- Optional SUB_INCLUDES mode, which allows to cross-include other localized text, so terms like city names can be kept at a central place.

How to Use

Language files are formatted as ruby hashes. An example file looks like this:

{ :messages => { :a => "Localized message text \\:", :b => "which also includes another text entry and displays a variable: \\v[1]" }, :actors => { 1 => { :name => "Name of Actor 1" } }, :maps => { 1 => "Display name of Map 1" }, :terms => { :command_new_game => "New Game command" }}Multiple files can be defined and will be merged together on game start. If a category appears in multiple files, all but one occurence of it will be lost unless DEEP_MERGE is set to true. In this case the script will merge the entries together.The current language can be read and changed by using:

IAVRA::I18N.languageIAVRA::I18N.language = :en # "en" works, tooConfigurationCore

- LANGUAGES: Contains the supported languages in symbol form. The entries will also be used as prefixes to load the language files on startup.

- FILE_PATH: %s will in turn be replaced with the string representation of a language (so, :en => "en") and be used as a file glob to determine which files should be loaded.

- PERSISTENCE: The file which is used to store the current language. This variable will be ignored, if the Game.ini Access script is present.

- DEEP_MERGE: If set to true, this will cause the language files to be combined with a recursive merge instead of a normal merge.

- SANDBOX: If set to true, a sandboxed eval (inside a thread with $SAFE = 4) will be used to read the language files instead of a regular eval.

Database

- CLEAN_ACTORS: As actors are stored inside $game_actors and not directly read from $data_actors, their localized attributes will, be default, be stored inside save files. Setting this to true causes the script to revert them to default before saving and re-localize them afterwards, leaving no trace inside the save files.

Messages

- MESSAGECODE: The message code, which is used to load localized text. The default is ":", which translates to "\:". Can be configured to allow compatibility with other scripts, that might be using this code.

- SUB_INCLUDES: If set to true, text entries in language files can reference other text entries (using the message code defined above). If set to false, our message code will be replaced with empty strings instead.

Terms of Use

Free to use for both commercial and non-commercial games. Please give credit.

Credits

Iavra

FAQ

Q: Will the message module auto-wrap my text to fit inside the message boxes?

A: No, i decided not to do this, since there are already other scripts that do this way better, than i ever could and that should be fully compatible.

Q: Does this include a menu that can be used to change the current language?

A: No, at this point the language is only change directly via script calls. If there is enough interest, i will write an additional module or plugin for Yanfly's System Options.

Q: Do i really have to write my language files in this strange syntax?

A: Currently, yes. Ruby hashes allow a lot of freedom to the expense of being more complicated than other file formats. If there is interest, i might write an external tool to manage the files, which will also marshal them, so you can put them inside the Data folder and include them in the encryption process. I certainly won't do this before IGMC, though.

Q: I don't want that localization stuff. Can i just use the script to load external text?

A: Sure you can! Set LANGUAGES = [] and PERSISTENCE = "". Note, that the "%s" in FILE_PATH will be replaced with an empty string in this case.

Changelog

- 1.00: Release version.

Download

Core engine: http://pastebin.com/n4wEwnBs

Database module: http://pastebin.com/WWWt5eGu

Messages module: http://pastebin.com/nbscF0W7
 
Last edited by a moderator:

Trihan

Speedy Scripter
Veteran
Joined
Apr 12, 2012
Messages
2,953
Reaction score
2,227
First Language
English
Primarily Uses
RMMV
Lookin' good! I'm not going to look at this yet in case it inadvertently influences my own take on localisation, which I'll be starting shortly, but once I'm done with mine I'm certainly going to have a gander. :)
 

AceOfAces_Mod

Engineering to infinity!
Veteran
Joined
Sep 7, 2014
Messages
1,726
Reaction score
1,203
First Language
Greek
Primarily Uses
RMVXA
Sign me up!
 

FeaR616

Veteran
Veteran
Joined
Nov 22, 2014
Messages
277
Reaction score
52
First Language
german
Primarily Uses
ooh, when I have more time, I try this out since I thought a lot about localizations of my game, but it has no priority yet.

so, if this works well, I can imagine to use this script! =)
 

Iavra

Veteran
Veteran
Joined
Apr 9, 2015
Messages
1,797
Reaction score
866
First Language
German
Primarily Uses
Modified the way language files are handled. In the new version the existing languages have to be defined beforehand like this:

LANGUAGES = [:de, :en]The first entry is used as the default language if the persistence file can't be found.Also, you define a file path template like this:

FILE_PATH = "I18N/%s{_*,}.rb"At game start, "%s" is replaced with the language string and the resulting string is given to Dir[] as a file glob. All found files are than evaluated as hashes and merged.The above file path for the language :de would match the files "I18N/de.rb" and "I18N/de_actors.rb". File globs are flexible enough so you can also use subfolders for structuring.

After the change, you no longer have to give the language inside the files, but have to give the category instead (see the updated comments inside the script).

Now you can put all your language definitions in one file (per language) or have them separated in categories like before.

/edit: If you want to add custom categories to the files and access them ingame, you can do so like this:

{   :category => {      :keyword => "value"   }} 
Code:
IAVRA::I18N[:category][:keyword]
//edit: I've thrown together a small add-on for messages:
Code:
#==========================================================================# Iavra Game Localization - Message Addon v0.1#==========================================================================module IAVRA	module I18N			module MESSAGES						#==========================================================================			# The category used inside language files to indicate messages.			#==========================================================================						CATEGORY = :messages						#==========================================================================			# The messagecode that should be replaced by i18n messages. Since the			# messages are also converted, it's possibly to cross-include and use other			# codes like \v[1] inside them. Note that you need an additional backslash			# in front of the codes, so you would write \\v[1] instead.			#==========================================================================						MESSAGECODE = ":"						#==========================================================================			# Building the regex, better not touch this part.			#==========================================================================						REGEX = /\e#{MESSAGECODE}\[(.+)\]/i						#==========================================================================			# Just a shorthand method.			#==========================================================================						def self.[](sym)				IAVRA::I18N[CATEGORY][sym]			end					end				endend#==========================================================================# ▼ Window_Base#==========================================================================class Window_Base < Window		alias :iavra_i18n_convert_escape_characters :convert_escape_characters		#==========================================================================	# make sure to call our own convert method, too.	#==========================================================================		def convert_escape_characters(text)		result = iavra_i18n_convert_escape_characters(text)		result = iavra_i18n_convert_message(result)		result	end		#==========================================================================	# I decided to put this in its own method, so it can be used from other	# methods as well.	#==========================================================================		def iavra_i18n_convert_message(text)		text.gsub(IAVRA::I18N::MESSAGES::REGEX) { 			convert_escape_characters(IAVRA::I18N::MESSAGES[$1.to_sym])		}	end	end
The language file would look like this:

Code:
{	:messages => {		:a => "test \\:[b]", 		:b => "sentence"	}}
Message in editor:
Code:
\:[a]
Message in game:
Code:
test sentence
WARNING: Since the given messages are recursively converted to make it possible to include other messages and codes like \v[1], it is also possible to create a loop by including a message in itself either direct or indirect. When this happens, your game obviously crashes, so don't do that.
 
Last edited by a moderator:

Trihan

Speedy Scripter
Veteran
Joined
Apr 12, 2012
Messages
2,953
Reaction score
2,227
First Language
English
Primarily Uses
RMMV
Great, more competition. :)

This seems to be coming along nicely, Iavra, nice one.
 

Iavra

Veteran
Veteran
Joined
Apr 9, 2015
Messages
1,797
Reaction score
866
First Language
German
Primarily Uses
Another update:

- Added experimental deep_merge functionality to the script that allows you to spread your categories over multiple files and tries to merge them together on game start. That means if you have the following files en_1.rb and en_2.rb:

{ :test => { 1 => "a" }}
Code:
{	:test => {		2 => "b"	}}
It will result in the following language map:
Code:
{	:en => {		:test => {			1 => "a", 			2 => "b"		}	}}
- modified the message add-on, so it converts our message code first to lessen the amount of work that has to be done recursively./edit: Restructured the code a bit, moved the configuration to the top and the file loading into DataManager.load_database, so it can be modified without touching the script itself.

//edit: Note that DEEP_MERGE is set to false by default, so if you want to use it, set it to true first ;)

///edit: The current language can now be saved to Game.ini instead of its own text file. All that's needed is to put my Game.ini Access script above this one: http://forums.rpgmakerweb.com/index.php?/topic/40347-iavra-gameini-access

Also, i fixed a bug regarding actors. Because they are cached in $game_actors, changes to $data_actors wouldn't get recognized (except the description, which for whatever reason is still read from the data, while name and nickname are copied during setup).

And i restructured the code a bit. Again.

////edit: Added support for map display names.

/////edit: (Damn, all those slashes...) Added an experimental sandbox mode. Since localization files are read in by using eval, there now exists the possibility to run the eval in its own thread by setting:

SANDBOX = true # default is falseThis causes the regular eval to be replaced by this:
Code:
def self.sandbox_eval(data)	Thread.new{		$SAFE = 4		Thread.current[:result] = eval(data)	}.join[:result]end
It's probably not needed, because the worst thing the user could do is crashing his/her own pc, but maybe someone wants to use it.Also note, that this is highly experimental and might cause lots of lags in addition, because it will create a new thread for every file read (though this happens only once every time the game is started).
 
Last edited by a moderator:

AceOfAces_Mod

Engineering to infinity!
Veteran
Joined
Sep 7, 2014
Messages
1,726
Reaction score
1,203
First Language
Greek
Primarily Uses
RMVXA
Errr, how do you create the language files?
 

Iavra

Veteran
Veteran
Joined
Apr 9, 2015
Messages
1,797
Reaction score
866
First Language
German
Primarily Uses
Manually, i personally use Notepad++. The file extension doesn't have to be .rb, but it causes Notepad++ to automatically highlight Ruby syntax.

You only have to make sure that you name your files according to your FILE_PATH:

FILE_PATH = "I18N/%s{_*,}.rb"This matches files like "I18N/en.rb", "I18N/en_actors.rb" and "I18N/en_whateveriwant111.rb"

/edit: I might be tempted to create a tool for managing files at one point, but that would be an external tool without ties to Ace. The advantage of this solution is that i could marshal the resulting files. This way it would be possible to encrypt them with the rest of the game and let load_data uncrypt them. But this is all "might" and depends on how well the script is received.
 
Last edited by a moderator:

AceOfAces_Mod

Engineering to infinity!
Veteran
Joined
Sep 7, 2014
Messages
1,726
Reaction score
1,203
First Language
Greek
Primarily Uses
RMVXA
I meant how the files must be created. For example, If I want to translate the "Attack" Command, I write on the file :command "string"
 

Iavra

Veteran
Veteran
Joined
Apr 9, 2015
Messages
1,797
Reaction score
866
First Language
German
Primarily Uses
By default, you would do this:

Code:
{    :terms => {        :command_attack => "..."    }}
 

AceOfAces_Mod

Engineering to infinity!
Veteran
Joined
Sep 7, 2014
Messages
1,726
Reaction score
1,203
First Language
Greek
Primarily Uses
RMVXA
if ARGV.include?("enlang")IAVRA::I18N.language = :enendif ARGV.include?("delang")IAVRA::I18N.language = :deendI wonder if this snippet will work, if somebody uses both this script and Tsukihime's Command-Line Args Loader (say the launcher detects the OS's language and launches the game by selecting the apropiate argument?
 
Last edited by a moderator:

Iavra

Veteran
Veteran
Joined
Apr 9, 2015
Messages
1,797
Reaction score
866
First Language
German
Primarily Uses
Modify DataManager.load_database like this:

def self.load_database iavra_i18n_load_database IAVRA::I18N.startup # put your snippet here # IAVRA::I18N.init_i18nendI commented the call to IAVRA::I18N.init_i18n because it will explicitly be called by setting the language, so it would run twice if i left it in./edit: A better way would be to overwrite load_language:

Code:
module IAVRA	module I18N		class << self			alias :original_load_language :load_language		end		def self.load_language			if ARGV.include?("enlang")				return :en			end			if ARGV.include?("delang")				return :de			end			original_load_language		end	endend
 
Last edited by a moderator:

Iavra

Veteran
Veteran
Joined
Apr 9, 2015
Messages
1,797
Reaction score
866
First Language
German
Primarily Uses
As it has been 3 days, i wanted to point out that the OP has been updated with the newest versions. The old script has been split into core engine and database module, so you don't have to use the database stuff if you only want your messages localized.


Feature-wise, i guess i have everything i wanted and i'm only some testing away from an "official" release. If there are any suggestions for features or additions to the FAQ, just let me know.
 

Iavra

Veteran
Veteran
Joined
Apr 9, 2015
Messages
1,797
Reaction score
866
First Language
German
Primarily Uses
Just wanted to give note, that this is now officially released. Have fun!
 

Necrofenser

Veteran
Veteran
Joined
May 2, 2013
Messages
43
Reaction score
4
First Language
Serbian
Primarily Uses
Maybe i am too stupid, but i cant figure out how to format text files, so i can load them in message window.

Also how do i load this text in game?

I am reading your post but somehow i can't figure that out 

Nevermind that, i figured it out!

Also, I can't download your Game.ini access script. Reupload please!
 
Last edited by a moderator:

Latest Threads

Latest Posts

Latest Profile Posts

Jeez...
I finally decide, after several ppl asking me to, to create a gamethread about project M... And my internet craps out on me halfway through the process :(
making my first game is like trying to stuff all my experience with old games into one
so its slow and painful when i dont get it right... i bet the next game is gonna be finished earlier!
When you don't find any time to work... :kaocry:
First Ten Minutes of my Caretaker inspired game

Finally, I got a good Gmail message [from smg5urded]
"This game does look a bit plain, but, I'm sure this does not destroy the experience as a whole. Monsters fit your style of game-play, mapping looks crude but I'm sure you can make it better if you do a remake of Forgotten Eclipse"

Forum statistics

Threads
110,397
Messages
1,052,967
Members
143,457
Latest member
BrainRot
Top