[XP][VXA] Localization

Started by ForeverZer0, July 26, 2012, 09:39:00 pm

Previous topic - Next topic

ForeverZer0

July 26, 2012, 09:39:00 pm Last Edit: April 22, 2013, 04:37:01 pm by KK20
Localization
Authors: ForeverZer0, KK20
Version: 1.1
Type: Multilingual Game Tool
Key Term: Game Utility



Introduction

This script adds support for creating games that support multiple languages. The files for each culture are in .ini format and located externally so that they can be easily translated and used by simply dropping the language file into the game's "Localization" folder.


Features


  • Uses IDs to get strings from external .ini files, which can be easily edited in any text editor, such as Notepad

  • Supports special characters used by non-English languages

  • Included message commands to simplify making your multilingual game, you use the command the same as you would the normal switch and variable commands

  • Also supports using in the Bitmap#draw_text methods so that custom scripts that draw onto Sprite bitmaps instead of Windows will still work without the need for customization

  • Automatically saves/loads the current culture




Screenshots

None.


Demo

[XP] Demo Link (Thank Google for the wonderful translations...)


Script

#+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
# Localization
# Author: ForeverZer0
# Version: 1.1
# Date: 7.27.12
#+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
#                             VERSION HISTORY
#+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
# v.1.0  7.26.12
#   - Initial release
# v.1.1  7.27.12
#   - Added ability to use any string as the ID instead of just numbers
#   - Added an alert message when a string is not found in the localization
#     file and the game is being ran in DEBUG mode
#+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
#
# Introduction:
#   This script adds support for creating games that support multiple languages.
#   The files for each culture are located externally so that they can be easily
#   translated and used by simply dropping the language file into the games
#   "Localization" folder.
#
# Features:
#   - Uses IDs to get strings from external .ini files, which can be easily
#     edited in any text editor such as Notepad
#   - Supports special characters used by non-English languages
#   - Included message commands to simplify making your multilangual game, you
#     use the command the same as you would the normal switch and variable
#     commands
#   - Also supports using in the Bitmap#draw_text methods so that custom scripts
#     that draw onto Sprite bitmaps instead of Windows will still work without
#     the need for customization
#   - Automatically saves/loads the current culture
#
# Instructions:
#   - Place the script anywhere in the editor
#   - Define the name of the language directory and default culture below
#   - The names of the cultures can be anything, I would stick to the convention
#     of naming files in the normal convention of "language-region" initials,
#     such as "en-US" (English, USA), "es-ES" (Spanish, Spain), etc., etc.
#   - Each language file should be a file with an .INI extension. If you are
#     unfamiliar with how .ini files are written, do a quick Google search, they
#     are quite simple.
#   - The .ini file should have only one section, which is the name of the
#     culture.
#             ex. [en-US]
#             ex. [es-ES]
#   - After that, you can simply begin to write the id-value pairs of each
#     string used in the culture.
#             ex. 1=This is a string
#             ex. 2=This is a string with ID 2
#             ex. GameIntro_01=This is a string with ID "GameIntro_01"
#   - Most importantly, the files must be saved in UTF-8 WITHOUT BOM. BOM stands
#     for "byte-order marker" and is a two byte value that is written to UTF8
#     files as a marker to other applications that they are encoded in UTF8.
#     WinAPI does not support this, so it must be saved without it. The text
#     will not appear if you fail to do this.
#   - Simply drop the completed files into the Localization folder
#   - To change the culture in game, use the following script command:
#         Localization.culture = CULTURE
#     CULTURE should be a string value that is the name of the file, without
#     extension
#             ex. Localization.culture = "en-US"
#  
#+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+

#===============================================================================
# ** Localization
#-------------------------------------------------------------------------------
# Static module for reading localized strings from language files.
#===============================================================================

module Localization
 #-----------------------------------------------------------------------------
 # * Constants
 #-----------------------------------------------------------------------------
 DIRECTORY = "Localization"
 DEFAULT_CULTURE = 'en-US'
 #-----------------------------------------------------------------------------
 # * Public instance variables.
 #-----------------------------------------------------------------------------
 attr_reader :culture
 attr_reader :filename
 #-----------------------------------------------------------------------------
 # * Initialize the localization module
 #-----------------------------------------------------------------------------
 def self.init
   @ini = Win32API.new('kernel32', 'GetPrivateProfileString', 'PPPPLP', 'L')
   unless File.directory?(DIRECTORY)
     Dir.mkdir(DIRECTORY)
   end
   path = ".\\#{DIRECTORY}\\CurrentCulture.txt"
   self.culture = File.exists?(path) ? IO.readlines(path)[0] : DEFAULT_CULTURE
 end
 #-----------------------------------------------------------------------------
 # * Set the current culture
 #-----------------------------------------------------------------------------
 def self.culture=(value)
   filename = ".\\#{DIRECTORY}\\#{value}.ini"
   if File.exists?(filename)
     @culture = value
     @filename = filename
     path = ".\\#{DIRECTORY}\\CurrentCulture.txt"
     File.open(path, 'wb') {|file| file.write(@culture) }
   else
     print "Cannot find language file for \"#{value}\"\n" +
       "Please ensure that the file \"#{filename}\" exists."
   end
 end
 #-----------------------------------------------------------------------------
 # * Read the string with the given ID of the current culture
 #-----------------------------------------------------------------------------
 def self.read(id)
   text = "\0" * 256
   @ini.call(@culture, id, '', text, 256, @filename)
   text.delete!("\0")
   if text == '' && $DEBUG
     print "No string defined!\nKey: \"#{id}\"\nCulture: \"#{@culture}\""
   end
   return text
 end
 #-----------------------------------------------------------------------------
 # * Parses a string for localization codes and returns it
 #-----------------------------------------------------------------------------
 def self.localize(string)
   if string != nil
     return string.gsub(/\\[Ll][Oo][Cc]\[(.+)\]/) { self.read($1) }
   end
 end
end

#===============================================================================
# ** Game_Temp
#===============================================================================

class Game_Temp
 #-----------------------------------------------------------------------------
 # * Overrids the setter for message text to localize the "Show Text" command
 #-----------------------------------------------------------------------------
 def message_text=(string)
   @message_text = Localization.localize(string)
 end
end

#===============================================================================
# ** Bitmap
#===============================================================================

class Bitmap
 #-----------------------------------------------------------------------------
 # * Replaces text based on the current culture
 #-----------------------------------------------------------------------------
 alias localized_draw_text draw_text
 def draw_text(*args)
   args.each_index {|i|
     args[i] = Localization.localize(args[i]) if args[i].is_a?(String) }
   localized_draw_text(*args)
 end
end

# Initialize static variables used in the module
Localization.init


#+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
# Localization
# Edit for VX-ACE by KK20
# Author: ForeverZer0
# Version: 1.1
# Date: 7.26.12
#+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
#                             VERSION HISTORY
#+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
# v.1.0  7.26.12
#   - Initial release
# v.1.1  7.27.12
#   - Added ability to use any string as the ID instead of just numbers
#   - Added an alert message when a string is not found in the localization
#     file and the game is being ran in DEBUG mode
#+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
#
# Introduction:
#   This script adds support for creating games that support multiple languages.
#   The files for each culture are located externally so that they can be easily
#   translated and used by simply dropping the language file into the games
#   "Localization" folder.
#
# Features:
#   - Uses IDs to get strings from external .ini files, which can be easily
#     edited in any text editor such as Notepad
#   - Supports special characters used by non-English languages
#   - Included message commands to simplify making your multilangual game, you
#     use the command the same as you would the normal switch and variable
#     commands
#   - Also supports using in the Bitmap#draw_text methods so that custom scripts
#     that draw onto Sprite bitmaps instead of Windows will still work without
#     the need for customization
#   - Automatically saves/loads the current culture
#
# Instructions:
#   - Place the script anywhere in the editor
#   - Define the name of the language directory and default culture below
#   - The names of the cultures can be anything, I would stick to the convention
#     of naming files in the normal convention of "language-region" initials,
#     such as "en-US" (English, USA), "es-ES" (Spanish, Spain), etc., etc.
#   - Each language file should be a file with an .INI extension. If you are
#     unfamiliar with how .ini files are written, do a quick Google search, they
#     are quite simple.
#   - The .ini file should have only one section, which is the name of the
#     culture.
#             ex. [en-US]
#             ex. [es-ES]
#   - After that, you can simply begin to write the id-value pairs of each
#     string used in the culture.
#             ex. 1=This is a string
#             ex. 2=This is a string with ID 2
#             ex. GameIntro_01=This is a string with ID "GameIntro_01"
#   - Most importantly, the files must be saved in UTF-8 WITHOUT BOM. BOM stands
#     for "byte-order marker" and is a two byte value that is written to UTF8
#     files as a marker to other applications that they are encoded in UTF8.
#     WinAPI does not support this, so it must be saved without it. The text
#     will not appear if you fail to do this.
#   - Simply drop the completed files into the Localization folder
#   - To change the culture in game, use the following script command:
#         Localization.culture = CULTURE
#     CULTURE should be a string value that is the name of the file, without
#     extension
#             ex. Localization.culture = "en-US"
#   
#+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+

#===============================================================================
# ** Localization
#-------------------------------------------------------------------------------
# Static module for reading localized strings from language files.
#===============================================================================

module Localization
  #-----------------------------------------------------------------------------
  # * Constants
  #-----------------------------------------------------------------------------
  DIRECTORY = "Localization"
  DEFAULT_CULTURE = 'en-US'
  #-----------------------------------------------------------------------------
  # * Public instance variables.
  #-----------------------------------------------------------------------------
  attr_reader :culture
  attr_reader :filename
  #-----------------------------------------------------------------------------
  # * Initialize the localization module
  #-----------------------------------------------------------------------------
  def self.init
    @ini = Win32API.new('kernel32', 'GetPrivateProfileString', 'PPPPLP', 'L')
    unless File.directory?(DIRECTORY)
      Dir.mkdir(DIRECTORY)
    end
    path = ".\\#{DIRECTORY}\\CurrentCulture.txt"
    self.culture = File.exists?(path) ? IO.readlines(path)[0] : DEFAULT_CULTURE
  end
  #-----------------------------------------------------------------------------
  # * Set the current culture
  #-----------------------------------------------------------------------------
  def self.culture=(value)
    filename = ".\\#{DIRECTORY}\\#{value}.ini"
    if File.exists?(filename)
      @culture = value
      @filename = filename
      path = ".\\#{DIRECTORY}\\CurrentCulture.txt"
      File.open(path, 'wb') {|file| file.write(@culture) }
    else
      print "Cannot find language file for \"#{value}\"\n" +
        "Please ensure that the file \"#{filename}\" exists."
    end
  end
  #-----------------------------------------------------------------------------
  # * Read the string with the given ID of the current culture
  #-----------------------------------------------------------------------------
  def self.read(id)
    text = "\0" * 256
    @ini.call(@culture, id, '', text, 256, @filename)
    text.delete!("\0")
    if text == '' && $DEBUG
      print "No string defined!\nKey: \"#{id}\"\nCulture: \"#{@culture}\""
    end
    return text
  end
  #-----------------------------------------------------------------------------
  # * Parses a string for localization codes and returns it
  #-----------------------------------------------------------------------------
  def self.localize(string)
    if string != nil
      return string.gsub(/\\[Ll][Oo][Cc]\[(.+)\]/) { self.read($1) }
    end
  end
end

#===============================================================================
# ** Game_Message
#===============================================================================

class Game_Message
  alias localized_text_add add
  def add(text)
    text = Localization.localize(text)
    strings = text.split("\\n")
    while strings.size > 0
      localized_text_add(strings.shift)
    end
  end
end

#===============================================================================
# ** Window_Base
#===============================================================================

class Window_Base
  alias localize_draw_text_ex draw_text_ex
  def draw_text_ex(x, y, text)
    text = Localization.localize(text)
    localize_draw_text_ex(x, y, text)
  end
end

#===============================================================================
# ** Bitmap
#===============================================================================

class Bitmap
  #-----------------------------------------------------------------------------
  # * Replaces text based on the current culture
  #-----------------------------------------------------------------------------
  alias localized_draw_text draw_text
  def draw_text(*args)
    args.each_index {|i|
      args[i] = Localization.localize(args[i]) if args[i].is_a?(String) }
    localized_draw_text(*args)
  end
end

# Initialize static variables used in the module
Localization.init



Instructions

Please see script for instructions.  The demo contains examples that will make much it much clearer.

How to Create a Language File: ShowHide

  • I highly suggest using Notepad++ to edit and create language files. It makes changing text encoding a simple click of the mouse (which is required), and syntax highlighting for .INI files. The rest of these instructions will be assuming you are using it.

  • Open up Notepad++ and create a new file. I strongly suggest to stick to the normal convention of naming files in the LANGUAGE-REGION format, where LANGUAGE and REGION are two-letter initials for their respective values. ex. "en-US", "en-GB", "fr-FR", etc., etc.

  • In the top menu bar, click "Encoding" and select "Encode in UTF-8 without BOM"

  • Create a section in the .ini file with the same name as the file (see image below)

  • Begin adding your id-string pairs into the file. The number/word for the IDs are arbitrary, but the they will be the numbers/word used to get the required strings throughout your game, so I recommend you use an order that helps you stay organized.

  • Save the file with an ".ini" extension by choosing "File" -> "Save As...", and selecting "MS ini file" from the combo box.

  • Drop the file into your game's "Localization" folder and set the current culture to the name you used, and your done.



How to use Localization in Your Game: ShowHide

  • Very simple. Pretty much anywhere you want to use a localized string, simply use the "\loc[ID]" command in place of the text, where the ID is obviously the ID specified in the language file.

  • This command can be used in "Show Text", "Show Choices", etc. commands, as well as within normal "draw_text" commands used by scripts. It can be used within the database editor for names of classes, words, elements, etc. Pretty much everywhere and anywhere. You may have to do a little search and replace of the few values that are hard-coded within the default scripts.

  • To change the current language, simply use the following command:

# This is an example, specify whatever culture you have defined
Localization.culture = 'en-US'





Compatibility

No known compatibility issues. Custom Message systems may require slight modification, though have not been tested. I can offer support for to making them compatible on a "per system" basis.


Credits and Thanks


  • ForeverZer0, for the script

  • KK20, for the VXA edit




Author's Notes

Please report bugs/issues so that may be resolved.
Feel free to request compatibility fixes if you have a Custom Message System that does not work with the script.
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

Blizzard

Just a small note: IDs should be strings as well. It's much easier to keep stuff in mind if you have strings as IDs/keys since it's easier to remember Forest_of_Illusion_Entry_Dialog_15 than 312547.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

ForeverZer0

There's actually nothing stopping you from using a string as it is right now, there would simply be a redundant "to_s" called on it. A string is actually what is passed to the API method.
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

G_G

This right here prevents us from using a string.
return string.gsub(/\\[Ll][Oo][Cc]\[([0-9]+)\]/) { self.read($1) }

ForeverZer0

Ah, shit, you're right, I'm thinking ahead to the next step. I can make a quick fix later, it will be simple.
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

Blizzard

Also test if newlines are processed properly. I'm not sure the .ini format allows processing them just like that.

Code: example
Intro_001=A long, long time ago in a
galaxy far, far away.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

G_G

Despite the minor detail, you still did a really nice job on this Zer0. It's a powerful script with so little code. Very well done!

Blizzard

I agree, cleverly executed. Have you thought about adding a debug-only window pop-up if a string has not been replaced? It would make finding unlocalized strings easier.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

ForeverZer0

Alrighty, I updated to allow strings as IDs as well. I also included the little pop-up window warning when strings are not found that Blizzard mentioned above (thanks).

After doing some testing and googling, Windows automatically escapes backslash characters within .ini files. This means that newline characters, etc. do not work. I spent about an hour trying to figure how to simply have the system look for escaped backslashes and convert them back, but I can't seem to get that to work.

I have also done a bit of messing around with Unicode characters, and am hitting a brick wall with that. Ruby 1.8.1 (RMXP's version) simply does not have enough Unicode support to be able to translate text into Chinese, Arabic, Japanese, and other languages like that. The strings are read being correctly from the .ini file (you can insert a "p text" in the read method before the return to see that much), but fail to be drawn correctly on windows. I have tried every sort of encoding combination, unpacking and repacking strings on the fly from UTF-8 to Latin, and nothing works. This is a issue with the underlying library that cannot be fixed with a script as far as I know how. Later version of Ruby (1.9 and above) fixed these issues, but I cannot find a proper work around that is gonna help when being stuck using Ruby 1.8.1.
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

Blizzard

You could use a custom .ini parser. Ruby 1.8.1 should properly read UTF8 encoded files. Just make sure that you skip the BOM at the beginning manually. You can refer to aprilui's Dataset::_loadTexts method to see how it's done. Keep in mind that Unicode != UTF8. I'm not sure if reading an .ini actually gives you Unicode characters. If yes, simply convert them to UT8. All my Input modules include a method for conversion, you can use that one.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

ForeverZer0

No, you misunderstand, the text being read from the files is correct. That's not the problem, I can use "p text" and the characters display perfectly in the little pop-up window, but if when you try to draw it to a window, nothing works. I could manually remove the BOM and it would make no difference. The BOM only has an effect on WinAPI, and has nothing to do with Ruby. I am saying that RMXP cannot handle the text.

This is what I am talking about. Put this code in the editor:
$data_system = load_data('Data/System.rxdata')
$game_system = Game_System.new
chinese = '你好世界。'
window = Window_Base.new(160, 208, 320, 96)
window.contents = Bitmap.new(192, 64)
window.contents.draw_text(0, 0, 192, 32, 'Encoding: ' + $KCODE, 1)
window.contents.draw_text(0, 32, 192, 32, 'Chinese:' + chinese, 1)
loop { Graphics.update; Input.update; break if Input.trigger?(Input::C) }

p chinese


Here are the results:
Spoiler: ShowHide

Spoiler: ShowHide
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

Blizzard

That's not RMXP being stupid there, that's the font not supporting the characters. Try "Arial Unicode MS" and/or "Arial Unicode MS Regular" and it should work.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

ForeverZer0

I have tried various Unicode fonts. They seem to have no problem displaying the same exact text in various other applications, but will not work in RMXP when I use the same exact font.
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

Blizzard

RMXP was originally Japanese software, that's really odd. :/
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

ForeverZer0

They are actually Chinese characters. I have yet to try Japanese.
I figured I would test with the most problematic, and if I can get that, its all good.

I still don't understand why the same text will display in one application and not RMXP, though.
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

azdesign

@ForeverZer0
There is nothing wrong with the font, look at this screenshot :

Spoiler: ShowHide



I'm using english RPG Maker and the japanese characters shown up properly in console window and message window.
All I did was to change the library using RGSS103J.dll. Set my locale to japanese, that's all.
That was a text from "show text". How about variable then? look at below screenshot :

Spoiler: ShowHide


That was from your script :

Spoiler: ShowHide

$data_system = load_data('Data/System.rxdata')
$game_system = Game_System.new
japs = 'こんにちわ'
window = Window_Base.new(160, 208, 320, 96)
window.contents = Bitmap.new(192, 64)
window.contents.draw_text(0, 0, 192, 32, 'Encoding : ' + $KCODE, 1)
window.contents.draw_text(0, 32, 192, 32, 'Japanese : ' + japs, 1)
loop { Graphics.update; Input.update; break if Input.trigger?(Input::C) }
p japs


So I think the problem is not on how RMXP draw the text, instead, how it store the text from external file.
I don't know if this help, but well, I just giving you my thoughts.
~ Check out my deviantart http://my-az-design.deviantart.com/ ~

Blizzard

Now we know what the update for RGSS103J.dll was for. xD
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

azdesign

August 01, 2012, 09:07:54 am #17 Last Edit: August 01, 2012, 09:14:40 am by azdesign
Showing japanese text problem has solved, but still no luck with showing japanese text from .ini file. Tried saving it into different encoding etc. The result was the text are invisible, or in random boxes.

Then I decided to do something much basic :

1. Create a plain text file encoded with UTF-8, inside the file, there are 2 lines, こんにちわ and はじめまして
2. Create a simple method to read a file and output each line using a window, save it, change the library to to RGSS103J.dll
3. Voila, the text properly extracted from .txt file and displayed properly just like the third screenshot from my last post.

Waiting for the next script update.  :)
~ Check out my deviantart http://my-az-design.deviantart.com/ ~

Rahvin

Hi,

I'm new to rpg maker and I'm using VX Ace.

I really need a localization script but I do not get this one to work.
I created the localization files as mentioned in the script but the translation does not work.

The script itself seems to get called as the CurrentCulture.txt file is created automatically when testing the game.

Im using the script for example in a show_text event as following: /loc[test_item]. The output in the game is [test_item].

Can anyone please help me to get this run under VX Ace or point me to another working localization script?

Many thanks in advance!

ThallionDarkshine

In the instructions it says to use \loc[id], not /loc[id]. Try using that.

Rahvin

Thanks for the reply.

I'm using \loc[id] in my script, it's just a typo in my thread.

KK20

Having not worked with VXA before, I'm not sure if this script--which is designed for XP--will work in VXA.

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

Rahvin

Yes, I'm afraid that this is the reason  :'(.

Unfortunately I did'nt find any other script for VX Ace.
Perhaps someone could take a look at the script and tell me what I have to modifiy to work under VX Ace. The script itself is not very large.

By the way, I did not find the definition of /loc[ID] in the script?
Where can I find the defintion of such commands in general?

KK20

April 15, 2013, 03:45:36 am #23 Last Edit: April 15, 2013, 10:17:28 pm by KK20
Downloaded VXA. Man this logical process is much more confusing than XP.
Spoiler: ShowHide

#+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
# Localization
# Edit for VX-ACE by KK20
# Author: ForeverZer0
# Version: 1.1
# Date: 7.26.12
#+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
#                             VERSION HISTORY
#+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
# v.1.0  7.26.12
#   - Initial release
# v.1.1  7.27.12
#   - Added ability to use any string as the ID instead of just numbers
#   - Added an alert message when a string is not found in the localization
#     file and the game is being ran in DEBUG mode
#+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
#
# Introduction:
#   This script adds support for creating games that support multiple languages.
#   The files for each culture are located externally so that they can be easily
#   translated and used by simply dropping the language file into the games
#   "Localization" folder.
#
# Features:
#   - Uses IDs to get strings from external .ini files, which can be easily
#     edited in any text editor such as Notepad
#   - Supports special characters used by non-English languages
#   - Included message commands to simplify making your multilangual game, you
#     use the command the same as you would the normal switch and variable
#     commands
#   - Also supports using in the Bitmap#draw_text methods so that custom scripts
#     that draw onto Sprite bitmaps instead of Windows will still work without
#     the need for customization
#   - Automatically saves/loads the current culture
#
# Instructions:
#   - Place the script anywhere in the editor
#   - Define the name of the language directory and default culture below
#   - The names of the cultures can be anything, I would stick to the convention
#     of naming files in the normal convention of "language-region" initials,
#     such as "en-US" (English, USA), "es-ES" (Spanish, Spain), etc., etc.
#   - Each language file should be a file with an .INI extension. If you are
#     unfamiliar with how .ini files are written, do a quick Google search, they
#     are quite simple.
#   - The .ini file should have only one section, which is the name of the
#     culture.
#             ex. [en-US]
#             ex. [es-ES]
#   - After that, you can simply begin to write the id-value pairs of each
#     string used in the culture.
#             ex. 1=This is a string
#             ex. 2=This is a string with ID 2
#             ex. GameIntro_01=This is a string with ID "GameIntro_01"
#   - Most importantly, the files must be saved in UTF-8 WITHOUT BOM. BOM stands
#     for "byte-order marker" and is a two byte value that is written to UTF8
#     files as a marker to other applications that they are encoded in UTF8.
#     WinAPI does not support this, so it must be saved without it. The text
#     will not appear if you fail to do this.
#   - Simply drop the completed files into the Localization folder
#   - To change the culture in game, use the following script command:
#         Localization.culture = CULTURE
#     CULTURE should be a string value that is the name of the file, without
#     extension
#             ex. Localization.culture = "en-US"
#  
#+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+

#===============================================================================
# ** Localization
#-------------------------------------------------------------------------------
# Static module for reading localized strings from language files.
#===============================================================================

module Localization
 #-----------------------------------------------------------------------------
 # * Constants
 #-----------------------------------------------------------------------------
 DIRECTORY = "Localization"
 DEFAULT_CULTURE = 'en-US'
 #-----------------------------------------------------------------------------
 # * Public instance variables.
 #-----------------------------------------------------------------------------
 attr_reader :culture
 attr_reader :filename
 #-----------------------------------------------------------------------------
 # * Initialize the localization module
 #-----------------------------------------------------------------------------
 def self.init
   @ini = Win32API.new('kernel32', 'GetPrivateProfileString', 'PPPPLP', 'L')
   unless File.directory?(DIRECTORY)
     Dir.mkdir(DIRECTORY)
   end
   path = ".\\#{DIRECTORY}\\CurrentCulture.txt"
   self.culture = File.exists?(path) ? IO.readlines(path)[0] : DEFAULT_CULTURE
 end
 #-----------------------------------------------------------------------------
 # * Set the current culture
 #-----------------------------------------------------------------------------
 def self.culture=(value)
   filename = ".\\#{DIRECTORY}\\#{value}.ini"
   if File.exists?(filename)
     @culture = value
     @filename = filename
     path = ".\\#{DIRECTORY}\\CurrentCulture.txt"
     File.open(path, 'wb') {|file| file.write(@culture) }
   else
     print "Cannot find language file for \"#{value}\"\n" +
       "Please ensure that the file \"#{filename}\" exists."
   end
 end
 #-----------------------------------------------------------------------------
 # * Read the string with the given ID of the current culture
 #-----------------------------------------------------------------------------
 def self.read(id)
   text = "\0" * 256
   @ini.call(@culture, id, '', text, 256, @filename)
   text.delete!("\0")
   if text == '' && $DEBUG
     print "No string defined!\nKey: \"#{id}\"\nCulture: \"#{@culture}\""
   end
   return text
 end
 #-----------------------------------------------------------------------------
 # * Parses a string for localization codes and returns it
 #-----------------------------------------------------------------------------
 def self.localize(string)
   if string != nil
     return string.gsub(/\\[Ll][Oo][Cc]\[(.+)\]/) { self.read($1) }
   end
 end
end

#===============================================================================
# ** Game_Message
#===============================================================================

class Game_Message
  alias localized_text_add add
  def add(text)
    text = Localization.localize(text)
    strings = text.split("\\n")
    while strings.size > 0
      localized_text_add(strings.shift)
    end
  end
end

#===============================================================================
# ** Window_Base
#===============================================================================

class Window_Base
 alias localize_draw_text_ex draw_text_ex
 def draw_text_ex(x, y, text)
   text = Localization.localize(text)
   localize_draw_text_ex(x, y, text)
 end
end

#===============================================================================
# ** Bitmap
#===============================================================================

class Bitmap
 #-----------------------------------------------------------------------------
 # * Replaces text based on the current culture
 #-----------------------------------------------------------------------------
 alias localized_draw_text draw_text
 def draw_text(*args)
   args.each_index {|i|
     args[i] = Localization.localize(args[i]) if args[i].is_a?(String) }
   localized_draw_text(*args)
 end
end

# Initialize static variables used in the module
Localization.init

If everything goes well, I'll tack this onto the OP.

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

Blizzard

April 15, 2013, 03:56:29 am #24 Last Edit: April 15, 2013, 03:58:16 am by Blizzard
If you want to mess arround a bit with automatic locale detection as well, here's some C++ code that should help you.

Code: cpp
			info.locale = "en"; // default is "en"
wchar_t locale[LOCALE_NAME_MAX_LENGTH] = {0};
int length = GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SABBREVLANGNAME,
locale, (LOCALE_NAME_MAX_LENGTH - 1) * sizeof(wchar_t));
if (length > 0)
{
info.locale = hstr::from_unicode(locale).lower();
if (info.locale.utf8_size() > 2)
{
info.locale = info.locale.utf8_substr(0, 2);
}
}


info.locale is a hstring, derived from std::string. The only problematic function would be hstr::from_unicode, but I implemented that one in my input module so you can reuse that. Also, hstring::operator() does the same as substr (first parameter is index, second is length).

EDIT: Hm... I fixed that to properly detect UTF8 codepoints.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

Rahvin

@KK20:
Thanks a lot, the script works fine :). What exactly did you change?!

@Blizzard:
Thanks for the tip. At the moment I stick to manual localization ;).

Rahvin

One issue ;):

Linebreaks are not working as mentioned in the thread before.

Can anyone tell me how rpg maker handels linebreaks?

I'd like to try to write something as using <br> in my localization-files for linebreaks and
replace them in rpg maker with correct linebreaks.
Any idea how to do this?

By the way, this forum is really great. Thanks for your support :)!

KK20

April 15, 2013, 05:43:00 pm #27 Last Edit: April 15, 2013, 10:15:34 pm by KK20
Replace Game_Message in my edit with this one:

#===============================================================================
# ** Game_Message
#===============================================================================

class Game_Message
  alias localized_text_add add
  def add(text)
    text = Localization.localize(text)
    strings = text.split("\\n")
    while strings.size > 0
      localized_text_add(strings.shift)
    end
  end
end

Now you can do something like this in the text files:
Quote1=This is the first string.\nNow the text is on the next line.
2=Double Line break!\n\nTada!
3=Actor name: \N[1] is not the same as \n line break.\n[1] won't return actor name obviously.


As for the exact changes I made, I replaced Game_Temp with the two classes Game_Message and Window_Base. Messages were interpreted through Game_Temp in RMXP, but in VXA it's done in these classes.

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

Rahvin

Thanks you very very much :)! Works great!

Rahvin

Unfortunately I'm facing another problem :(, perhaps you can help me once again.

I'd like to use this quest-log script: http://rmrk.net/index.php/topic,45127.0.html

You have do edit the quest-details in the script. Of course I need them localized, too.

I placed the quest-log-script under the localization script in the script editor and I have tried something like this in line 779 of the script:
q[:name]              = Localization.localize("quest_name")


Unfortunately the text shown in the quest_log is "quest_name" and not the localized text.
How can I call the localization script inside another script?

KK20

April 18, 2013, 06:25:55 pm #30 Last Edit: April 22, 2013, 04:37:55 pm by KK20

q[:name] = Localization.localize("\\loc[quest_name]")


EDIT:
Modified the first post to include the VXA edit I created.

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

Tassilo

Most wonderful, we are successfully using it for our 16-Bit version of Days of Dawn (https://www.kickstarter.com/projects/bumblebee/days-of-dawn-discover-the-magic).
Would it be possible to add a "change language" button to the main menu? One that cycles through the available languages and would keep it's name in english. Thus is would be named "Switch language", no matter which one is selected, but cycle through the currently installed language files one after another, showcasing the chosen language by updating the other title screen entries to that language.
Could anybody maybe assist me in doing such?
Thank you very much!
All the best,
Tassilo

Zexion

Sure i can do that if you send me the scripts involved.

Tassilo

That would be super-fantastic!
I'm currently using Title Arranger as found on http://area91.multiverseworks.com/blog/rmvxa_script/menu/title_rearranger to extend my title screen menu.
What I'd love to have now is a "Switch language" entry that would cycle through "Localization"'s available languages.

Thank you so much,
Tassilo

Quote from: Zexion on January 02, 2015, 03:37:23 pm
Sure i can do that if you send me the scripts involved.

Zexion

January 04, 2015, 09:30:54 pm #34 Last Edit: January 05, 2015, 06:58:41 am by Zexion
I wasn't sure how to do this without closing the command window to refresh it, so I'm sorry if that isn't what you wanted. The button changes the current Language but to see the results, you have to change the words themselves to the \loc[ID] version.
"New Game", "Continue", and "Exit" are in the database under the "Terms" tab.
"Game over" is in this script on line 176.
Spoiler: ShowHide
#==============================================================================
#
# GaryCXJk - Title Rearranger v1.00
# * Last Updated: 2012.12.28
# * Level: Easy
# * Requires: N/A
#
#==============================================================================

$imported = {} if $imported.nil?
$imported["CXJ-TitleRearranger"] = true

#==============================================================================
#
# Changelog:
#
#------------------------------------------------------------------------------
# 2012.12.30 - v1.00
#
# * Initial release
#
#==============================================================================
#
# I have the tendency to write test code, and sometimes I want to see the
# results without having to go through the main game. At other times, I just
# want to add new functionality to the title screen, for example, to have a
# settings menu, or to show a credits screen.
#
# Which is why I made this script. Because I'm a programmer, ergo, because I'm
# lazy.
#
#==============================================================================
#
# Installation:
#
# Make sure to put this below Materials, but above Main Process.
#
# This script adds aliases for several methods. If you are sure no method that
# is used by other scripts get overridden, you can place it anywhere,
# otherwise, make sure this script is loaded after any other script overriding
# these methods, otherwise this script stops working.
#
#------------------------------------------------------------------------------
# Aliased methods:
#
# * class Window_TitleCommand
#   - make_command_list
# * class Scene_Title
#   - create_command_window
#
#==============================================================================
#
# Usage:
#
# This script generally is plug-and-play, and therefore requires nothing much.
# All you have to do is follow the instructions of the part that can be
# modified safely, which I hope is clear enough to understand. After that it's
# just running the script.
#
#==============================================================================
#
# License:
#
# Creative Commons Attribution 3.0 Unported
#
# The complete license can be read here:
# http://creativecommons.org/licenses/by/3.0/legalcode
#
# The license as it is described below can be read here:
# http://creativecommons.org/licenses/by/3.0/deed
#
# You are free:
#
# to Share -- to copy, distribute and transmit the work
# to Remix -- to adapt the work
# to make commercial use of the work
#
# Under the following conditions:
#
# Attribution -- You must attribute the work in the manner specified by the
# author or licensor (but not in any way that suggests that they endorse you or
# your use of the work).
#
# With the understanding that:
#
# Waiver -- Any of the above conditions can be waived if you get permission from
# the copyright holder.
#
# Public Domain -- Where the work or any of its elements is in the public domain
# under applicable law, that status is in no way affected by the license.
#
# Other Rights -- In no way are any of the following rights affected by the
# license:
#
# * Your fair dealing or fair use rights, or other applicable copyright
#   exceptions and limitations;
# * The author's moral rights;
# * Rights other persons may have either in the work itself or in how the work
#   is used, such as publicity or privacy rights.
#
# Notice -- For any reuse or distribution, you must make clear to others the
# license terms of this work. The best way to do this is with a link to this
# web page.
#
#------------------------------------------------------------------------------
# Extra notes:
#
# Despite what the license tells you, I will not hunt down anybody who doesn't
# follow the license in regards to giving credits. However, as it is common
# courtesy to actually do give credits, it is recommended that you do.
#
# As I picked this license, you are free to share this script through any
# means, which includes hosting it on your own website, selling it on eBay and
# hang it in the bathroom as toilet paper. Well, not selling it on eBay, that's
# a dick move, but you are still free to redistribute the work.
#
# Yes, this license means that you can use it for both non-commercial as well
# as commercial software.
#
# You are free to pick the following names when you give credit:
#
# * GaryCXJk
# * Gary A.M. Kertopermono
# * G.A.M. Kertopermono
# * GARYCXJK
#
# Personally, when used in commercial games, I prefer you would use the second
# option. Not only will it actually give me more name recognition in real
# life, which also works well for my portfolio, it will also look more
# professional. Also, do note that I actually care about capitalization if you
# decide to use my username, meaning, capital C, capital X, capital J, lower
# case k. Yes, it might seem stupid, but it's one thing I absolutely care
# about.
#
# Finally, if you want my endorsement for your product, if it's good enough
# and I have the game in my posession, I might endorse it. Do note that if you
# give me the game for free, it will not affect my opinion of the game. It
# would be nice, but if I really did care for the game I'd actually purchase
# it. Remember, the best way to get any satisfaction is if you get people to
# purchase the game, so in a way, I prefer it if you don't actually give me
# a free copy.
#
# This script was originally hosted on:
# http://area91.multiverseworks.com
#
#==============================================================================
#
# The code below defines the settings of this script, and are there to be
# modified.
#
#==============================================================================

module CXJ
 module TITLE_REARRANGER
   
   #------------------------------------------------------------------------
   # Add the commands in the order you want it to be displayed.
   #------------------------------------------------------------------------
   COMMANDS = [
   :new_game,
   :continue,
   :switch_language,
   :gameover,
   :shutdown,
   ]
   
   #------------------------------------------------------------------------
   # Add handlers for your meth ods here. This assumes you know scripting.
   # Both the activation state flag and the extra arbitrary data are called
   # using methods, as the data is most likely dynamic and therefore cannot
   # be initialized here. You can leave these two out if you're not going
   # to use them, or set them as nil.
   #------------------------------------------------------------------------
   NEW_COMMANDS = {
   # :command  => [ "Display Name",  Handler Method, Enabled Method, Ext Data Method],
     :gameover => [ "Game Over",   :cxj_tr_gameover, nil, nil],
     :switch_language => [ "Language", :zex_sw_lang, nil, nil ],
   }
   
   #------------------------------------------------------------------------
   # Add methods below, or in the class Scene_Title.
   # It is preferable to add them to the Scene_Title class for better
   # compatibility, which is why there is a special block below. However,
   # in most instances you could put the methods here if you want to, for
   # example to keep the code as clean as possible.
   #------------------------------------------------------------------------
 end
end

#==============================================================================
# ** Scene_Title
#------------------------------------------------------------------------------
#  This class performs the title screen processing.
#------------------------------------------------------------------------------
#  Add methods below.
#==============================================================================
class Scene_Title < Scene_Base
 #--------------------------------------------------------------------------
 # * Show Game Over Screen
 #--------------------------------------------------------------------------
 def cxj_tr_gameover
   close_command_window
   SceneManager.call(Scene_Gameover)
 end
 #--------------------------------------------------------------------------
 # * Change the current language
 #--------------------------------------------------------------------------
 def zex_sw_lang
   # Close the Command Window while updating
   close_command_window
   # Initialize if needed
   if @lang_index == nil
     # Initialize language variables
     @lang_index = 0
     @languages = Dir.entries(Localization::DIRECTORY)
     # Deletes non language entries from the array
     @languages.delete(".")
     @languages.delete("..")
     @languages.delete("CurrentLanguage.txt")
     # Removes .ini from file names
     @languages.each{|lang| lang.slice!(".ini")}
     # Set the total number of languages
     @size = @languages.size - 1
   end
   # Increase the index
   if @lang_index < @size
     @lang_index += 1
   else
     @lang_index = 0
   end
   # Change Current Language
   Localization.language = @languages[@lang_index]
   # Open command window in new language
   create_command_window
 end
end

#==============================================================================
#
# The code below should not be altered unless you know what you're doing.
#
#==============================================================================

#==============================================================================
# ** Window_TitleCommand
#------------------------------------------------------------------------------
#  This window is for selecting New Game/Continue on the title screen.
#==============================================================================

class Window_TitleCommand < Window_Command
 #--------------------------------------------------------------------------
 # * Alias: Create Command List
 #--------------------------------------------------------------------------
 alias window_titlecommand_make_command_list_cxj_tr make_command_list
 def make_command_list
   window_titlecommand_make_command_list_cxj_tr
   CXJ::TITLE_REARRANGER::NEW_COMMANDS.each do |key, value|
     is_enabled = true
     if value.size > 2 && !value[2].nil?
       enabled_method = method(value[2]) if respond_to?(value[2])
       enabled_method = CXJ::TITLE_REARRANGER.method(value[2]) if enabled_method.nil? && CXJ::TITLE_REARRANGER.respond_to?(value[2])
       is_enabled = enabled_method.call if(!enabled_method.nil?)
     end
     ext = nil
     if value.size > 3 && !value[3].nil?
       ext_method = method(value[3]) if respond_to?(value[3])
       ext_method = CXJ::TITLE_REARRANGER.method(value[3]) if ext_method.nil? && CXJ::TITLE_REARRANGER.respond_to?(value[3])
       ext = ext_method.call if !ext_method.nil?
     end
     add_command(value[0], key, is_enabled, ext)
   end
   command_list = CXJ::TITLE_REARRANGER::COMMANDS
   new_list = Array.new(command_list.size)
   @list.each do |value|
     next if !command_list.include?(value[:symbol])
     new_list[command_list.index(value[:symbol])] = value
   end
   @list = new_list
 end
end

#==============================================================================
# ** Scene_Title
#------------------------------------------------------------------------------
#  This class performs the title screen processing.
#==============================================================================
class Scene_Title < Scene_Base
 #--------------------------------------------------------------------------
 # * Alias: Create Command Window
 #--------------------------------------------------------------------------
 alias scene_title_create_command_window_cxj_tr create_command_window
 def create_command_window
   scene_title_create_command_window_cxj_tr
   CXJ::TITLE_REARRANGER::NEW_COMMANDS.each do |key, value|
     handler_method = method(value[1]) if respond_to?(value[1])
     handler_method = CXJ::TITLE_REARRANGER.method(value[1]) if handler_method.nil? && CXJ::TITLE_REARRANGER.respond_to?(value[1])
     @command_window.set_handler(key, handler_method) if !handler_method.nil?
   end
 end
end

Tassilo

Wow, outstanding, thanks a lot!
I'm running into an error right now though: Switching the language, I'm getting
"Script 'Title Rearranger' line 242: NoMethodError occured.
undefined method 'language=' for Localization:Module.


The line (in my version of the script) is:
   
Localization.language = @languages[@lang_index]

The Localization-script is placed above the TitleArranger script in the project.

Thanks so much!

Zexion

January 05, 2015, 06:56:08 am #36 Last Edit: January 05, 2015, 06:59:37 am by Zexion
I forgot to mention that it bases the language on the filename itself instead of reading the first line of the file (just because they should be the same). So if your file name is "English.ini" and the actual language code is en-US then it won't work :s

Just incase, what are the contents of the 'Localization' folder?

Or even, did you rename the localization folder, because I forgot to even take that into account. fixed

Tassilo

In my /Localization there is:
CurrentCulture.txt (containing "en-US")
de-DE.ini
en-US.ini

Zexion

January 05, 2015, 08:05:25 am #38 Last Edit: January 05, 2015, 08:12:56 am by Zexion
Did you modify the script in anyway? Because I'm testing it out on a blank project and it works fine with the same files and everything o.o

You could try adding :
msgbox @languages[@lang_index]
above the error line and tell me what it says.

Tassilo

January 06, 2015, 02:55:54 am #39 Last Edit: January 06, 2015, 03:32:11 am by KK20
I did some (minor) modifications, like localizing the entries and adding a credits entry. I just tried with your exact copy of TitleRearranger and keep getting the same error.
Requesting the lang_index gives me "de_DE", which is correct and would be the next language to chose.

Quote from: Zexion on January 05, 2015, 08:05:25 am
Did you modify the script in anyway? Because I'm testing it out on a blank project and it works fine with the same files and everything o.o

You could try adding :
msgbox @languages[@lang_index]
above the error line and tell me what it says.


EDIT: I just put both of your scripts including the Localization folder into another project and keep getting the same error. What might I be doing wrong? Did you do any changes to your Localization-script since 1.1?
Thank you so much for your patience!

EDIT 2: Okay, got it. Checked your Localizationscript and have seen, that the method is called "Localization.culture" instead of "Localization.language" in the version I've got installed. Should have found that earlier. Working like a charm now, thank you!

Zexion

Sorry i was busy today, but that's right. I forgot that I changed culture to language. I didn't think of that because I thought i had used the script from the original demo :P
Glad u figured it out though.

Rairun

December 22, 2015, 09:02:47 pm #41 Last Edit: December 22, 2015, 09:04:45 pm by Rairun
Great script! I have two questions:

- If I decide to go commercial with my game (not sure I will), am I allowed to use the VXA version of this script?

- I have been able to make this script work with pretty much all text I'm using in my game, except for this modified version of an Atelier RGSS script. Would it be complicated to make both scripts work together? I need to be able to have a comment like <Text = \loc[1]>

#==============================================================================
# +++ MOG - Event Text Popup (v1.1) +++
#==============================================================================
# By Moghunter
# https://atelierrgss.wordpress.com/
#- English
#1 - You're free to use all Atelier-Rgss scripts in commercial or non-commercial projects.
#2 - You're free to edit and adapt my scripts.
#==============================================================================
# Apresenta o um texto em cima do evento.
#==============================================================================
# Para ativa basta colocar um comentário com o prefixo:
#
# <Text = X>
# <Offset_text = x, y>
#
# X - Texto apresentado no evento.
#
# Exemplo
#
# <Text = Teleport>
# <Text = Save Point>
#
#==============================================================================
module MOG_EVENT_TEXT_POPUP
 #Definição da fonte.
 FONT_SIZE = 16
 FONT_BOLD = true
 FONT_COLOR = Color.new(255,255,255)
 #Definição da prioridade do Texto
 SCREEN_Z = 550
end  

#==============================================================================
# ■ Game CharacterBase
#==============================================================================
class Game_CharacterBase  
 attr_accessor :text
 attr_accessor :opacity
 attr_accessor :erased
 attr_accessor :offset_text
end

#==============================================================================
# ■ Game Event
#==============================================================================
class Game_Event < Game_Character  
 
#--------------------------------------------------------------------------
# ● Setup Page Setting
#--------------------------------------------------------------------------                    
 alias mog_event_text_setup_page_settings setup_page_settings
 def setup_page_settings
     mog_event_text_setup_page_settings
     setup_event_text
     setup_event_offset_text
 end
   
#--------------------------------------------------------------------------
# ● Setup Event Text
#--------------------------------------------------------------------------                      
 def setup_event_text
     return if @list == nil
     for command in @list
     if command.code == 108
        if command.parameters[0] =~ /<Text = ([^>]*)>/
           @text = $1
 
        end  
      end
     end
  end

  #
def setup_event_offset_text
     return if @list == nil
    for command in @list
    if command.code == 108
       if command.parameters[0] =~ /<Offset_text = (\-?\d+), (\-?\d+)>/
           @offset_text = [$1.to_i, $2.to_i]
           p @offset_text
        end
      end
     end
 end  
 
  #
 

end  

#==============================================================================
# ■ Sprite Character Text
#==============================================================================
class Sprite_Character_Text < Sprite_Base
 
 include MOG_EVENT_TEXT_POPUP
 
#--------------------------------------------------------------------------
# ● Initialize
#--------------------------------------------------------------------------                    
 def initialize(viewport = nil,character,sprite)
     super(viewport)
     text_size = character.text.to_s.split(//)
     w = 32 + (FONT_SIZE / 2) * text_size.size rescue nil
     w = 32 if w == nil or w < 32
     self.bitmap = Bitmap.new(w,32)
     self.bitmap.font.size = FONT_SIZE
     self.bitmap.font.bold = FONT_BOLD
     self.bitmap.font.color = FONT_COLOR
     self.bitmap.draw_text(0,0,self.width,self.height,character.text.to_s,1) rescue nil
     update_position(character,sprite)
 end
 
#--------------------------------------------------------------------------
# ● Dispose
#--------------------------------------------------------------------------                    
 def dispose
     super
     self.bitmap.dispose
 end  

#--------------------------------------------------------------------------
# ● Update Position
#--------------------------------------------------------------------------                    
 def update_position(character,sprite)
     if character.erased
        self.visible = false
        return
      end
     self.x = character.screen_x - self.width / 2 + character.offset_text[0]
     self.y = character.screen_y - (sprite.height + self.height) + character.offset_text[1]
     self.z = character.screen_z + SCREEN_Z
     self.visible = character.transparent == true ? false : true
     self.opacity = character.opacity
 end

end

#==============================================================================
# ■ Sprite Character
#==============================================================================
class Sprite_Character < Sprite_Base

#--------------------------------------------------------------------------
# ● Initialize
#--------------------------------------------------------------------------                    
 alias mog_event_text_initialize initialize
 def initialize(viewport, character = nil)
     mog_event_text_initialize(viewport, character)
     @character_text = ""
     @character_offset_text = [0,0]
     create_event_text
 end  
 
#--------------------------------------------------------------------------
# ● Create Event Text
#--------------------------------------------------------------------------                    
 def create_event_text
     return if @character == nil
     return if @character.text == nil
     return if @character.text == @character_text
     dispose_event_text
   if Input.press?(:X)
     @event_text = Sprite_Character_Text.new(viewport,@character,self)
     @character_text = @character.text
     @character_offset_text = @character.offset_text
   end
 end

#--------------------------------------------------------------------------
# ● Dispose
#--------------------------------------------------------------------------                  
 alias mog_event_text_dispose dispose
 def dispose
     mog_event_text_dispose
     dispose_event_text
 end  
 
#--------------------------------------------------------------------------
# ● Dispose Event Text
#--------------------------------------------------------------------------                    
 def dispose_event_text
     return if @event_text == nil
     @event_text.dispose ; @event_text = nil
     @character_offset_text = [0,0]
 end
 
#--------------------------------------------------------------------------
# ● Update
#--------------------------------------------------------------------------                    
 alias mog_event_text_update update
 def update
     mog_event_text_update
     create_event_text ; update_event_text
 end  
 
#--------------------------------------------------------------------------
# ● Update Event Text
#--------------------------------------------------------------------------                    
 def update_event_text
     return if @event_text == nil
     if Input.press?(:X)
     @event_text.update_position(@character,self)
   else
     @character_text = ""
     end
 end
   
end

$mog_rgss3_event_text_popup = true

KK20

Because the XP version does not have any terms of use, VXA does not either.

Try replacing:

  def setup_event_text
      return if @list == nil
      for command in @list
      if command.code == 108
         if command.parameters[0] =~ /<Text = ([^>]*)>/
            @text = Localization.localize($1)
   
         end 
       end
      end
   end

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

Rairun

December 23, 2015, 05:04:43 am #43 Last Edit: December 23, 2015, 05:56:51 am by Rairun
Sorry if I'm being stupid, but I just want to be 100% sure - does having no terms of use amount to being free to use commercially? I ask because I don't have any terms of use for my photography, for example, but I'm pretty sure I could still enforce copyright if I wanted to.

Also, thanks! I'm going to try again tonight when I'm on my laptop, but I think I've tried your exact solution, and it didn't work. :( If I remember it correctly, it threw a script error here:

      self.x = character.screen_x - self.width / 2 + character.offset_text[0]


EDIT: Actually, no, that would make no sense. I think the script error happened when I included \loc[1] in the comment without modifying the script. When I modified the script, I believe I got a method error? I'll check again tonight.

KK20

Unless the script explicitly says you can't use it in commercial games (without the creator's consent), then the script can be freely used anywhere. There's no mention of that on the OP, so you are allowed to assume that the script can be used commercially.

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

Rairun

Thanks for the info!

Also, you were right, your change fixes the issue! I initially got a crash, but it was because I made a mistake setting up the text offset - nothing to do with the localization part. Cheers.

orochii

Hi, sorry for posting in this old topic but I needed to get this out of my chest. For some reason I had been having problems with "special" characters such as áéíóú♥. For some reason it showed diamonds with question marks (a.k.a. unknown characters), depending on how many bytes it comprised of, so for example á showed 2 and ♥ showed 3 of these unknown characters.

I did achieve to fix it on my game after some experimentation, trial, error, and reading some StackOverflow. The thing is that I found that, for some reason, strings read from the INI file, even if the INI file is UTF8 with no BOM, were formatted in ASCII 8-bit. Much more weird is the fact that printing them with a regular draw_text works just fine. But things like letter-by-letter messages, or anything that reads one character at a time, did show these as unknown characters.

So anyway, I fixed it by doing this. I modified the self.localize method, just by adding force_encoding.
#-----------------------------------------------------------------------------
  # * Parses a string for localization codes and returns it
  #-----------------------------------------------------------------------------
  def self.localize(string)
    if string != nil
      return string.gsub(/\\[Ll][Aa][Nn][Gg]\[(.+)\]/) { a = self.read($1).force_encoding('UTF-8')}
    end
  end

Seems to work fine because the data it reads it's actually UTF-8, so it really doesn't need to reconvert, just remember it that it is a UTF-8 string, not ASCII! Same bytes, wrong way of reading.

I don't know if anyone else had this problem, but I just wanted to share, since it gave me some pain.

Blizzard

There is something with String#scan with "./m" or something similar that solves this problem. I did this in RMX-OS with the chatbox. Download RMX-OS and search for scan in the client script.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.