Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Multiple Language XP

Multiple Language Script
v0.54


I posted a screen in the respective thread, and now I finally post the script... Let's see if someone can put it in good use besides me ^_^


Introduction

This scripts purpose is to make your game multiple language-ready. It enables an interface launched before the title screen to select a language to play with. The list shown there consists of folder names inside your Game/Language directory.
The big idea is to make the language of a game independent from the native language of the creator and/or his foreign language skills. Of course, if you're going to release it in an English community and your game is English from the begin with, you won't need to do the (relatively big) efford and implement this.


Screenshots




Script and Resources

Code:
#==============================================================================

# Multiple Language Script

#------------------------------------------------------------------------------

# Script by BlueScope

#==============================================================================

 

class Game_System

  #--------------------------------------------------------------------------

  attr_accessor :language

  #--------------------------------------------------------------------------

  def read_text(id)

    file = File.open("Language/" + @language + "/Generic.txt")

    content = file.readlines

    for line in 0..content.size-1

      if content[line].include?("*" + id)

        temp_content = content[line]

        temp_content.gsub!(("*" + id + " "), "")

      end

    end

    return temp_content

  end

  #--------------------------------------------------------------------------

  def read_base(id)

    file = File.open("Language/" + @language + "/Database.txt")

    content = file.readlines

    id = id.split(" ")

    for line in 0..content.size-1

      if content[line].include?("*" + id[0])

        temp_content = content[line]

        temp_content.gsub!(("*" + id[0] + " "), "")

      end

    end

    return temp_content

  end

  #--------------------------------------------------------------------------

end

 

 

class Window_Version < Window_Base

  #--------------------------------------------------------------------------

  def initialize

    super(320, 176, 240, 128)

    self.contents = Bitmap.new(width - 32, height - 32)

    refresh

  end

  #--------------------------------------------------------------------------

  def refresh

    self.contents.clear

    self.contents.font.color = system_color

    self.contents.draw_text(4, 0, self.width-40, 32, $game_system.read_text("00000"), 0)

    self.contents.draw_text(4, 37, self.width-40, 32, $game_system.read_text("00002"), 0)

    self.contents.draw_text(4, 64, self.width-40, 32, $game_system.read_text("00004"), 0)

    self.contents.font.color = normal_color

    self.contents.draw_text(4, 0, self.width-40, 32, $game_system.read_text("00001"), 2)

    self.contents.draw_text(4, 37, self.width-40, 32, $game_system.read_text("00003"), 2)

    self.contents.draw_text(4, 64, self.width-40, 32, "1.0", 2) # Game Version

    self.contents.fill_rect(4, 34, self.width-40, 1, disabled_color)

  end

  #--------------------------------------------------------------------------

end

 

 

class Window_CommandLanguage < Window_Selectable

  #--------------------------------------------------------------------------

  def initialize(width, commands)

    super(0, 0, width, commands.size * 32 + 32)

    @item_max = commands.size

    @commands = commands

    self.contents = Bitmap.new(width - 32, @item_max * 32)

    self.opacity = 0

    refresh

    self.index = 0

  end

  #--------------------------------------------------------------------------

  def refresh

    self.contents.clear

    for i in 0...@item_max

      draw_item(i, normal_color)

    end

  end

  #--------------------------------------------------------------------------

  def draw_item(index, color)

    self.contents.font.color = color

    rect = Rect.new(4, 32 * index, self.contents.width - 8, 32)

    self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))

    self.contents.draw_text(rect, @commands[index], 1)

  end

  #--------------------------------------------------------------------------

  def disable_item(index)

    draw_item(index, disabled_color)

  end

  #--------------------------------------------------------------------------

end

 

 

class Scene_Language

  #--------------------------------------------------------------------------

  def main

    $game_system = Game_System.new

    $data_system = load_data("Data/System.rxdata")

    @command_window = Window_CommandLanguage.new(240, read_languages)

    @command_window.x = 80

    @command_window.y = 240 - @command_window.height / 2

    $game_system.language = read_languages[@command_window.index]

    @version_window = Window_Version.new

    @dummy = Window_Base.new(80, 176, 240, 128)

    Graphics.transition

    loop do

      Graphics.update

      Input.update

      update

      if $scene != self

        break

      end

    end

    Graphics.freeze

    @command_window.dispose

    @version_window.dispose

    @dummy.dispose

  end

  #--------------------------------------------------------------------------

  def read_languages

    entries = Dir.entries("Language/.")

    entries.delete_at(0)

    entries.delete_at(0)

    entries.sort!

    return entries

  end

  #--------------------------------------------------------------------------

  def update

    @command_window.update

    if Input.trigger?(Input::UP) or Input.trigger?(Input::DOWN)

      $game_system.language = read_languages[@command_window.index]

      @version_window.refresh

    end

    if Input.trigger?(Input::C)

      $scene = Scene_Title.new

    end

  end

  #--------------------------------------------------------------------------

end

 

 

class Scene_Title

  #--------------------------------------------------------------------------

  def command_new_game

    $game_system.se_play($data_system.decision_se)

    Audio.bgm_stop

    Graphics.frame_count = 0

    $game_temp          = Game_Temp.new

    $game_switches      = Game_Switches.new

    $game_variables     = Game_Variables.new

    $game_self_switches = Game_SelfSwitches.new

    $game_screen        = Game_Screen.new

    $game_actors        = Game_Actors.new

    $game_party         = Game_Party.new

    $game_troop         = Game_Troop.new

    $game_map           = Game_Map.new

    $game_player        = Game_Player.new

    $game_party.setup_starting_members

    $game_map.setup($data_system.start_map_id)

    $game_player.moveto($data_system.start_x, $data_system.start_y)

    $game_player.refresh

    $game_map.autoplay

    $game_map.update

    $scene = Scene_Map.new

  end

  #--------------------------------------------------------------------------

end
*00000 Author
*00001 BlueScope
*00002 Language Version
*00003 1.0
*00004 Game Version

Instructions

Script Installation":28pbyzrk said:
Of course, you first have to copy the script part in the script editor, in a new script above Main. The script is plug-and-play, besides a single thing: You need to trigger it in Main, so head for this line:
Code:
  # Make scene object (title screen)

  $scene = Scene_Title.new
Go change it to this:
Code:
  # Make scene object (language selection screen)

  $scene = Scene_Language.new
Now you have to create files to store your strings in. I posted an example file further above that only includes the language menu. Create a new directory inside your game's folder and save the content of the spoiler in a txt file named "Generic.txt". Note that you also need other files for several areas where strings are used. The path should be [Game Directory]\Language\English\[filename].txt, if you chose English to be your language of choice. Here's the list of files you need currently, along with an explanation of what they contain:
Code:
Language\[language]\Generic.txt   # read with $game_system.read_text(id); used for draw_text strings within the script editor

Language\[language]\Database.txt  # read with $game_system.read_base(id); used for strings like item names or class names within the Database
Note that if you're going to use special characters the English language doesn't know, you should use UTF-8 encoding for the txt file which you can choose while saving. It will show German dieresis and Japanese Kana and Kanji in RMXP this way. Credit for this hint goes to Selwyn, who told me this some time ago.
Since the language scene isn't the only thing you'd want to be translated, I'll tell you how to mark other strings as ones to be replaced.

First, you might want to replace strings defined in the script editor, like the ones in command windows and such. I'll take the title screen as an example, which of course is classed in Scene_Title.
What we need to look at is this:
Code:
    # Make command window

    s1 = [color=Blue]"New Game"[/color]

    s2 = "Continue"

    s3 = "Shutdown"

    @command_window = Window_Command.new(192, [s1, s2, s3])
Three strings are defined there. Let's replace "New Game" only for space-saving purposes in this example. Of course, we first need a new entry in the language file, so fire it up. Create a new identification line and a string, so it looks like this (default part left out):
*00005 New Game
Now that you created the string, you need to create a reference. Open Scene_Title again, and replace the default s1 line with this:
Code:
    s1 = [color=Blue]$game_system.read_text("00005")[/color]
Try it out by testplaying your game.
System strings are strings defined in the database's system tab, in the column 'Words'. You can't simply put a number inside these to replace the strings, you need to manually replace the references in the script editor. You might also overwrite RPG::System::Words, which can be found in RMXPs help file.
I'll take Window_Gold as an example this time, and I'll use the replacement method. Let's take a look at the important part...
Code:
  def refresh

    self.contents.clear

    cx = contents.text_size([color=Blue]$data_system.words.gold[/color]).width

    self.contents.font.color = normal_color

    self.contents.draw_text(4, 0, 120-cx-2, 32, $game_party.gold.to_s, 2)

    self.contents.font.color = system_color

    self.contents.draw_text(124-cx, 0, cx, 32, [color=Blue]$data_system.words.gold[/color], 2)

  end
$data_system.words.gold is in there two times. This line holds the string; you could write "Gold", too, for example. Well, in order to have the currency name tagged, you need to replace these references. I won't explain how to create a language string in the txt file, but here's how your Window_Gold part should look like if you used 00006 as the currency identifier:
Code:
  def refresh

    self.contents.clear

    cx = contents.text_size([color=Blue]$game_system.read_text("00006")[/color]).width

    self.contents.font.color = normal_color

    self.contents.draw_text(4, 0, 120-cx-2, 32, $game_party.gold.to_s, 2)

    self.contents.font.color = system_color

    self.contents.draw_text(124-cx, 0, cx, 32, [color=Blue]$game_system.read_text("00006")[/color], 2)

  end
Note that you probably won't need to translate the currency name at all... it was just an example from me, if you don't see a reason why it should be replaced, don't include it in the language file.
Another important part to translate are database strings, like item names, which I'll take as the example this time. In Window_Item, there's a single line refering to the name:
Code:
self.contents.draw_text(x + 28, y, 212, 32, [color=Blue]item.name[/color], 0)
Let's assume we want to translate the default #0001 item: Potion. Note that for database items, you have to use entries in the Database.txt located in your language's folder. After you created your language string in the txt file (number "00001" for this example - note that you can of course use multiple instances of the same number as long it's referencing to different files), replace the line I posted before with this:
Code:
self.contents.draw_base(x + 28, y, 212, 32, [color=Blue]$game_system.read_base(item.name)[/color], 0)
Now you only need to name the item properly. Instead of Potion, you have to name it 00001 now. It's important to not include quotation marks in here, you'll get an error if you try. Note that you can name the item something like 00001 Potion, as everything behind the number (as long as it's seperated with a space) gets ignored by the respective method.
This works with all the database strings, you just need to find the respective places to change the reference inside the script editor. Once again, pay attention on what you translate - you probably don't want your heroes to have different names in different languages, as this might be confusing.
ToDo-List

- Only launch up the language selection screen if there's more than one language folder in the 'Language' folder
- Read the default language from compiled Data directory to make it inaccessable to the player
- Adjust Scene_Load to only show files with the language currently selected
- Window_Message support
- Easier language tagging and language file handling


Frequently Asked Questions

None so far...


Compatibility

This should be compatible with everything because it doesn't change and/or overwrite any of the default methods.


Credits

BlueScope ^_^
vgvgf for helping me out with a file reading problem I couldn't solve by myself.
Chaosg1 for helping me out with the global variable replacing.
 
Whoa!
A script which that work! XD Kidding mate.
I have to say, Im impressed. Its really awesome.
I look forward to more development. :D
(BTW: Im Kurisu if you didn't know that :P )
 
@Dopey: LOL, and I wondered who the fuck tried to piss me off XD
Well, thanks anyway ;)

@vgvgf: I prefer the number way, but of course you can replace it with whatever you want to have. You need to pay attention, though, because I used 'include?' and not '==', so if you'd have '*Item' before '*Item02', it'd always return 'Item' for obvious reasons. The reason why I used 'include?' is that you can write anything you want behind the reference tag, for example '*00001 # Stores the 'Author' string', which also eases up the whole overview...
 
You need to trigger it in Main, so head for this line:

You don't have to do that. See here:

Code:
begin
  Graphics.freeze
  $scene = Scene_Language.new
  $scene.main
end

Then just turn $scene to nil when you exit the scene. The title screen will play fine afterwards. Just have this script placed directly above Main.


The message support could be done a few ways I see it:
~ Create Conditional Statements
~ Create additional windows and such (Language/World ID/NPC ID.txt)
Instead of displaying the text, have a script run through lines in the text document.
Code:
play_text_line(event.id, start_line_number...stop_line_number)

Code:
class Interpreter
  def event
    return $game_map.events[@event_id]
  end
  def play_text_line(event_id, range)
    $game_temp.message_text = ''
    lines = File.readlines("Language/#{$game_map.map_id}/#{event_id}.txt)
    for i in range
      $game_temp.message_text = += lines[i] + '/n'
    end
  end
end

Something like that.


Great stuff BS.
 
I'm aware of the fact that you can have multiple scene layers, but I dislike them nevertheless... it seems cleaner to me without it, and besides, if someone else uses this method, one of the scripts wouldn't work... wouldn't suit this script well, as it's made for maximum compatibility ^_^

For the message thing, I was going to use the method I have now... and Tricks draw_wrap_text method once again :P (fucking useful :) ) I also thought about sticking with a single file for each language, but I had the each-map-a-file-way in my mind, too... you don't happen to have a method to read stuff from zip files, have ya? XD

Oh, and thanks ^_^
 
Zip files use a very powerfull encoding codes, almost impossible to break, belive I have tried :)

OTher than that, that's avery nice script! I would never though of that.
 
Hm... I guess I could use folders then... as soon as someone tells me how to get the names of all folders in a directory instead of the filenames :D

And thanks ^_^
 
Hehe, that's one of the advantages of this script: You don't have to be able to know two languages perfect. You might find a person who is kind enough to translate the game for you into another language without the need of giving them the uncompiled game - just pass them the language file!
 
I updated the script with a few little things. First of all, I decided to use the multiple txt file system now, so you have a folder called [whatever language you want to have] and files called "Generic.txt" and "Database.txt" inside (more to come). I guess that this is as practical as the way I had it before, and it's also easier to overview...
Along with the database reading method, I thought that it'd be way to stressy to look up every ID in the database if you want to add an item or whatever via events. That's why I changed the method a little and made it comment-compatible, meaning nothing else than you can write whatever you desire behind the ID without being seen anywhere ingame.
Lastly, I rewrote the reading method a little so IDs and the content are in one line, contributing to the general overview if you're working on your language file.

Oh, and I got rid of the $language global with Chaos' help... added him to the credits and updated the script.

Hope you like it the way it is now, but stay tuned for updates and bring in some suggestions.
 
Well, either you named a folder or the file itself wrong (remember to spell case-sensitive) or you placed the Language folder in the wrong directory... remember it should be in the game directory, not in the Graphics or whatever dir.

If it's none of that, I can't really imagine what should cause an error message like that...
 
BlueScope;261760 said:
Well, either you named a folder or the file itself wrong (remember to spell case-sensitive) or you placed the Language folder in the wrong directory... remember it should be in the game directory, not in the Graphics or whatever dir.

If it's none of that, I can't really imagine what should cause an error message like that...

Everything is right, but not work...

Do i need to import that to somewhere or make some options?
 
Ok, I have a question. My title screen uses images for the text. Is there a way that I can tell it use a different image file depending on the language?

Edit: Nevermind. I found a way.

Edit2: Ok I found a flaw in the script. If the text file is unicode then it RMXP displays and error message. Without unicode character such as "Ä
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top