From cfd30bbca6d809fbef6a9d3f054e910be4a5ee5a Mon Sep 17 00:00:00 2001 From: tdixon Date: Fri, 3 Mar 2017 16:53:16 -0400 Subject: [PATCH] Enable localization of game text --- scripts/EdText.rb | 2 +- scripts/Interpreter 3.rb | 12 ++++--- scripts/Main.rb | 1 - scripts/Persistent.rb | 6 +++- scripts/Scene_Map.rb | 2 +- scripts/Window_MainMenu.rb | 12 ++++--- scripts/Window_Settings.rb | 65 +++++++++++++++++++++++++++------ scripts/_scripts.txt | 2 +- scripts/i18n_Language.rb | 74 ++++++++++++++++++++++++++++++++++---- 9 files changed, 144 insertions(+), 32 deletions(-) diff --git a/scripts/EdText.rb b/scripts/EdText.rb index 310bdad..0a15263 100644 --- a/scripts/EdText.rb +++ b/scripts/EdText.rb @@ -25,9 +25,9 @@ module EdText sleep 0.2 end result = nil + text = Language.tr(text.to_s.gsub(/\s*\n\s*/, " ").strip) thread = Thread.new do result = Oneshot.msgbox(type, text - .gsub(/\s+\n\s+/, " ") .gsub("\\p", $game_oneshot.player_name) + " " * 10) # HACK: Fuck diff --git a/scripts/Interpreter 3.rb b/scripts/Interpreter 3.rb index b1e3647..616d100 100644 --- a/scripts/Interpreter 3.rb +++ b/scripts/Interpreter 3.rb @@ -19,6 +19,10 @@ class Interpreter # Create full text string choices = false text = @list[@index].parameters[0].strip + + # Translate text + text = Language.tr(text).clone + if text.start_with?('$') is_doc = true text.slice!(0) @@ -31,11 +35,11 @@ class Interpreter # 401: another line of text if @list[@index+1].code == 401 @index += 1 - text << " " << @list[@index].parameters[0].rstrip + text << " " << Language.tr(@list[@index].parameters[0].rstrip).clone elsif @list[@index+1].code == 101 && (is_doc || is_credits) # 101: Another message box # Tack on if we're a doc - new_text = @list[@index+1].parameters[0].strip + new_text = Language.tr(@list[@index+1].parameters[0].strip).clone if new_text.start_with?('$') text << "\n\n" << new_text[1..-1] @index += 1 @@ -64,9 +68,7 @@ class Interpreter end text.gsub!(/\s*\\n\s*/, '\\n') text.strip! - - # Translate text - text = Language.tr(text).clone + text = Language.tr(text) # Parse first line for portrait specifier if text[0,1] == '@' diff --git a/scripts/Main.rb b/scripts/Main.rb index aa260bd..8555851 100644 --- a/scripts/Main.rb +++ b/scripts/Main.rb @@ -16,7 +16,6 @@ begin # Load persistent data Persistent.load - $persistent.lang = 'ja' # Prepare for transition Graphics.freeze diff --git a/scripts/Persistent.rb b/scripts/Persistent.rb index 069af95..b0351ed 100644 --- a/scripts/Persistent.rb +++ b/scripts/Persistent.rb @@ -38,6 +38,10 @@ class Persistent end Language.set(@lang) end + + def langcode + self.lang.full.to_s + end # MARSHAL def marshal_dump @@ -49,7 +53,7 @@ class Persistent # Save/Load global instance of persistent FILE_NAME = Oneshot::SAVE_PATH + '/persistent.dat' - def self.save + def save File.open(FILE_NAME, 'wb') do |file| Marshal.dump($persistent, file) end diff --git a/scripts/Scene_Map.rb b/scripts/Scene_Map.rb index 4198a11..4fb5ba4 100644 --- a/scripts/Scene_Map.rb +++ b/scripts/Scene_Map.rb @@ -98,7 +98,7 @@ class Scene_Map # either telling them they can't quit during a cutscene # or telling them they're saving and quitting if $game_system.map_interpreter.running? - EdText.info("You cannot perform this action during cutscenes.") + EdText.info(tr("You cannot perform this action during cutscenes.")) return else $game_temp.common_event_id = 35 diff --git a/scripts/Window_MainMenu.rb b/scripts/Window_MainMenu.rb index 905183f..9d87f8d 100644 --- a/scripts/Window_MainMenu.rb +++ b/scripts/Window_MainMenu.rb @@ -5,9 +5,9 @@ class Window_MainMenu < Window_Selectable # Set up menu options @commands = Array.new - @commands << tr('Travel') - @commands << tr('Notes') - @commands << tr('Settings') + @commands << 'Travel' + @commands << 'Notes' + @commands << 'Settings' @item_max = @commands.size @column_max = @item_max @@ -47,7 +47,7 @@ class Window_MainMenu < Window_Selectable # Update item rect = Rect.new(w * index, 0, w - 32, 32) self.contents.fill_rect(rect, Color.new(0, 0, 0, 0)) - self.contents.draw_text(rect, @commands[index], 1) + self.contents.draw_text(rect, tr(@commands[index]), 1) end #-------------------------------------------------------------------------- # * Disable Item @@ -59,6 +59,10 @@ class Window_MainMenu < Window_Selectable # Open/show the menu def open + # redraw in case language has been updated + for i in 0...@item_max + draw_item(i, normal_color) + end self.opacity = 0 self.contents_opacity = 0 self.visible = true diff --git a/scripts/Window_Settings.rb b/scripts/Window_Settings.rb index db8ff30..0962e1a 100644 --- a/scripts/Window_Settings.rb +++ b/scripts/Window_Settings.rb @@ -7,14 +7,15 @@ class Window_Settings SETTINGS_FILE_NAME = Oneshot::SAVE_PATH + '/settings.conf' def save_settings + $persistent.save File.open(SETTINGS_FILE_NAME, 'w') do |file| - file.puts('bgm_volume=' + Audio.bgm_volume.to_s) - file.puts('sfx_volume=' + Audio.sfx_volume.to_s) - file.puts('fullscreen=' + Graphics.fullscreen.to_s) - file.puts('default_run=' + $game_switches[251].to_s) - file.puts('colorblind_mode=' + $game_switches[252].to_s) - file.puts('frameskip=' + Graphics.frameskip.to_s) - end + file.puts('bgm_volume=' + Audio.bgm_volume.to_s) + file.puts('sfx_volume=' + Audio.sfx_volume.to_s) + file.puts('fullscreen=' + Graphics.fullscreen.to_s) + file.puts('default_run=' + $game_switches[251].to_s) + file.puts('colorblind_mode=' + $game_switches[252].to_s) + file.puts('frameskip=' + Graphics.frameskip.to_s) + end end def self.load_settings @@ -75,6 +76,7 @@ class Window_Settings @title.bitmap.font.size = 40 @title.y = TITLE_TOP_MARGIN @title.x = MARGIN + Language.register_text_sprite(self.class.name + "_title", @title) @data_sprites = [] @viewport.z = 9998 @@ -110,10 +112,16 @@ class Window_Settings tr('Default movement'), tr('Colorblind mode'), tr('Frameskip'), + tr('Language'), tr('Configure Controls (Press F1)'), ] @index = 0 + # Load our language settings from persistent, stored differently + @lang_index = Language::LANGUAGES.index($persistent.langcode) + if @lang_index.nil? + @lang_index = 0 + end # Create title @title.bitmap.clear @@ -126,6 +134,7 @@ class Window_Settings spr.x = MARGIN spr.y = TITLE_MARGIN + TITLE_TOP_MARGIN + ITEM_SPACING * i spr.opacity = 0 + Language.register_text_sprite(self.class.name + "_option_#{i}", spr) redraw_setting(spr, i) @data_sprites << spr @@ -168,9 +177,13 @@ class Window_Settings else spr.bitmap.draw_text(260, 0, spr.bitmap.width, spr.bitmap.height, tr("OFF")) end - end + when 6 # Language + l = Language::LANGUAGES[@lang_index] rescue Language::LANGUAGES[0] + spr.bitmap.draw_text(260, 0, spr.bitmap.width, spr.bitmap.height, l) + end end - + + def redraw_setting_index(i) if !@data_sprites.kind_of?(Array) return @@ -181,6 +194,16 @@ class Window_Settings redraw_setting(@data_sprites[i], i) end + + def redraw_all_settings + @title.bitmap.clear + @title.bitmap.draw_text(0, 0, @title.bitmap.width, @title.bitmap.height, tr("Settings")) + for i in 0..7 + redraw_setting_index(i) + end + end + + def update if @fade_in self.opacity += 20 @@ -276,15 +299,16 @@ class Window_Settings Audio.bgm_volume -= 1 if old_vol > 1 Audio.se_play("Audio/SE/text_robot.wav", 70, (Audio.bgm_volume/2) + 75) + redraw_setting_index(0) end elsif Input.trigger?(Input::RIGHT) || (Input.press?(Input::RIGHT) && (@right_hold_timer >= 15)) @right_hold_timer -= 2 Audio.bgm_volume += 1 if old_vol < 100 Audio.se_play("Audio/SE/text_robot.wav", 70, (Audio.bgm_volume/2) + 75) + redraw_setting_index(0) end end - redraw_setting_index(0) when 1 #sfx vol old_vol = Audio.sfx_volume @@ -293,15 +317,16 @@ class Window_Settings Audio.sfx_volume -= 1 if old_vol > 1 Audio.se_play("Audio/SE/text_robot.wav", 70, (Audio.sfx_volume/2) + 75) + redraw_setting_index(1) end elsif Input.trigger?(Input::RIGHT) || (Input.press?(Input::RIGHT) && (@right_hold_timer >= 15)) @right_hold_timer -= 2 Audio.sfx_volume += 1 if old_vol < 100 Audio.se_play("Audio/SE/text_robot.wav", 70, (Audio.sfx_volume/2) + 75) + redraw_setting_index(1) end end - redraw_setting_index(1) when 2 #fullscreen if Input.trigger?(Input::ACTION) || Input.trigger?(Input::LEFT) || Input.trigger?(Input::RIGHT) @@ -354,6 +379,24 @@ class Window_Settings end redraw_setting_index(5) end + + when 6 #language + if Input.trigger?(Input::ACTION) || Input.trigger?(Input::RIGHT) + @lang_index += 1 + if @lang_index >= Language::LANGUAGES.length + @lang_index = 0 + end + $persistent.lang = Language::LANGUAGES[@lang_index] + redraw_all_settings() + end + if Input.trigger?(Input::LEFT) + @lang_index -= 1 + if @lang_index < 0 + @lang_index = Language::LANGUAGES.length - 1 + end + $persistent.lang = Language::LANGUAGES[@lang_index] + redraw_all_settings() + end end if Input.trigger?(Input::CANCEL) diff --git a/scripts/_scripts.txt b/scripts/_scripts.txt index e4e58ea..9f9b48c 100644 --- a/scripts/_scripts.txt +++ b/scripts/_scripts.txt @@ -100,7 +100,7 @@ Persistent # Internationalization i18n_Language -i18n_English +i18n_Japanese # Data Data_Item diff --git a/scripts/i18n_Language.rb b/scripts/i18n_Language.rb index 8581c12..e01a34d 100644 --- a/scripts/i18n_Language.rb +++ b/scripts/i18n_Language.rb @@ -1,32 +1,56 @@ # Classes for translating text similar to GNU gettext # Translator class: translate text to another language + +# for debug REMOVE BEFORE COMMITTING +require "zlib" + class Language FONT_WESTERN = 'Terminus (TTF)' FONT_CJK = 'WenQuanYi Micro Hei' + LANG_WESTERN = [ + 'en', 'fr', 'pt_BR' + ] + LANG_CJK = [ + 'ja', 'ko', 'zh_CN' + ] + LANGUAGES = LANG_WESTERN + LANG_CJK class << self def set(lc) + dbg_print(lc.lang) + @data = nil @tr = nil script = nil [lc.full.to_s, lc.lang.to_s].each do |name| - begin - @tr, script = load_data("Languages/#{name}.rxdata") - break - rescue + path = "Languages/#{name}.loc" + dbg_print(path) + if FileTest.exist?(path) + File.open(path, "rb") do |file| + @data = Marshal.load(file) + if LANG_CJK.include? name + Font.default_name = FONT_CJK + else + Font.default_name = FONT_WESTERN + end + end end end - exec(script) if script + reset_fonts(@text_sprites) Oneshot.set_yes_no(tr('Yes'), tr('No')) end # Translate some text def tr(string) + #dbg_print(caller_locations(1, 1).first.tap{|loc| puts "#{loc.path}:#{loc.lineno}"}) + dbg_print(string) if @data - @data[Zlib::crc32(string)] || string + rv = @data[Zlib::crc32(string)] || string else - string + rv = string end + dbg_print(rv) + return rv end # Turn all database items into translatable strings @@ -41,6 +65,42 @@ class Language end end end + + def dbg_print(str) + dbg = IO.new(STDERR.fileno) + if str.nil? + dbg.write("null\n") + else + dbg.write(str.to_s + "\n") + end + dbg.close() + end + + def register_text_sprite(key, spr) + dbg_print(key) + if @text_sprites.nil? + @text_sprites = Hash.new() + end + @text_sprites[key] = spr + end + + def reset_fonts(sprites) + if sprites.kind_of?(Array) + sprites.each do |spr| + if spr.kind_of?(Sprite) + spr.bitmap.font.name = Font.default_name + end + end + elsif sprites.kind_of?(Hash) + sprites.each_value do |spr| + if spr.kind_of?(Sprite) + spr.bitmap.font.name = Font.default_name + end + end + elsif sprites.kind_of?(Sprite) + sprites.bitmap.font.name = Font.default_name + end + end end end