mirror of
https://forgejo.xatacraft.ru/Sunshine/mkxp-sunshine.git
synced 2026-08-20 22:09:55 +00:00
Preliminary i18n improvements
This commit is contained in:
parent
a4de9d9f10
commit
546f29f42e
15 changed files with 166 additions and 59 deletions
|
|
@ -150,8 +150,7 @@ rb_get_args(int argc, VALUE *argv, const char *format, ...)
|
|||
VALUE *str = va_arg(ap, VALUE*);
|
||||
VALUE tmp = *arg;
|
||||
|
||||
if (!RB_TYPE_P(tmp, RUBY_T_STRING))
|
||||
rb_raise(rb_eTypeError, "Argument %d: Expected string", argI);
|
||||
tmp = rb_str_to_str(tmp);
|
||||
|
||||
*str = tmp;
|
||||
++argI;
|
||||
|
|
@ -169,8 +168,7 @@ rb_get_args(int argc, VALUE *argv, const char *format, ...)
|
|||
|
||||
VALUE tmp = *arg;
|
||||
|
||||
if (!RB_TYPE_P(tmp, RUBY_T_STRING))
|
||||
rb_raise(rb_eTypeError, "Argument %d: Expected string", argI);
|
||||
tmp = rb_str_to_str(tmp);
|
||||
|
||||
*s = RSTRING_PTR(tmp);
|
||||
*len = RSTRING_LEN(tmp);
|
||||
|
|
@ -188,8 +186,7 @@ rb_get_args(int argc, VALUE *argv, const char *format, ...)
|
|||
|
||||
VALUE tmp = *arg++;
|
||||
|
||||
if (!RB_TYPE_P(tmp, RUBY_T_STRING))
|
||||
rb_raise(rb_eTypeError, "Argument %d: Expected string", argI);
|
||||
tmp = rb_str_to_str(tmp);
|
||||
|
||||
*s = RSTRING_PTR(tmp);
|
||||
++argI;
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ void oneshotBindingInit()
|
|||
//Constants
|
||||
rb_const_set(module, rb_intern("USER_NAME"), rb_str_new2(shState->oneshot().userName().c_str()));
|
||||
rb_const_set(module, rb_intern("SAVE_PATH"), rb_str_new2(shState->oneshot().savePath().c_str()));
|
||||
rb_const_set(module, rb_intern("LANG"), ID2SYM(rb_intern(shState->oneshot().lang().c_str())));
|
||||
rb_const_set(module, rb_intern("LANG"), rb_str_new2(shState->oneshot().lang().c_str()));
|
||||
rb_const_set(msg, rb_intern("INFO"), INT2FIX(Oneshot::MSG_INFO));
|
||||
rb_const_set(msg, rb_intern("YESNO"), INT2FIX(Oneshot::MSG_YESNO));
|
||||
rb_const_set(msg, rb_intern("WARN"), INT2FIX(Oneshot::MSG_WARN));
|
||||
|
|
|
|||
|
|
@ -65,8 +65,13 @@ void steamBindingInit()
|
|||
/* Constants */
|
||||
#ifdef STEAM
|
||||
rb_const_set(module, rb_intern("USER_NAME"), rb_str_new2(shState->steam().userName().c_str()));
|
||||
if (shState->steam().lang().empty())
|
||||
rb_const_set(module, rb_intern("LANG"), Qnil);
|
||||
else
|
||||
rb_const_set(module, rb_intern("LANG"), rb_str_new2(shState->steam().lang().c_str()));
|
||||
#else
|
||||
rb_const_set(module, rb_intern("USER_NAME"), Qnil);
|
||||
rb_const_set(module, rb_intern("LANG"), Qnil);
|
||||
#endif
|
||||
|
||||
/* Functions */
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ class Ed_Message
|
|||
widths = []
|
||||
|
||||
# Pre-process text
|
||||
text_raw = $game_temp.message_ed_text
|
||||
text_raw = $game_temp.message_ed_text.to_str
|
||||
|
||||
# Substitute variables, actors, player name, newlines, etc
|
||||
text_raw.gsub!(/\\v\[([0-9]+)\]/) do
|
||||
|
|
|
|||
|
|
@ -6,34 +6,13 @@ class Game_Oneshot
|
|||
attr_accessor :plight_timer # start of plight's plight
|
||||
|
||||
def initialize
|
||||
user_name = Oneshot::USER_NAME.split(/\s+/)
|
||||
user_name = (Steam.enabled? ? Steam::USER_NAME : Oneshot::USER_NAME).split(/\s+/)
|
||||
if user_name[0].casecmp('the') == 0 || user_name[0].casecmp('a') == 0
|
||||
@player_name = user_name.join(' ')
|
||||
else
|
||||
@player_name = user_name[0]
|
||||
end
|
||||
@lights = {}
|
||||
self.lang = Oneshot::LANG
|
||||
@plight_timer = nil
|
||||
end
|
||||
|
||||
# lang
|
||||
def lang
|
||||
@lang
|
||||
end
|
||||
def lang=(val)
|
||||
@lang = val
|
||||
$tr = Translator.new(val)
|
||||
$language = Language.get(val)
|
||||
Font.default_name = $language.font
|
||||
Oneshot.set_yes_no(tr('Yes'), tr('No'))
|
||||
end
|
||||
|
||||
# MARSHAL
|
||||
def marshal_dump
|
||||
[@player_name, @lang, @plight_timer]
|
||||
end
|
||||
def marshal_load(array)
|
||||
@player_name, self.lang, @plight_timer = array
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ begin
|
|||
Graphics.frame_rate = 60
|
||||
Font.default_size = 20
|
||||
|
||||
# Load persistent data
|
||||
Persistent.load
|
||||
|
||||
# Prepare for transition
|
||||
Graphics.freeze
|
||||
# Make scene object (title screen)
|
||||
|
|
|
|||
63
scripts/Persistent.rb
Normal file
63
scripts/Persistent.rb
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
# Persistent data independent from save file.
|
||||
# Stores settings and the like.
|
||||
class LanguageCode
|
||||
attr_accessor :full
|
||||
attr_accessor :lang
|
||||
attr_accessor :region
|
||||
|
||||
def initialize(str)
|
||||
parts = str.split(/[_-]/)
|
||||
if parts.size == 1
|
||||
@lang, @region = parts.first.downcase.to_sym, nil
|
||||
@full = @lang
|
||||
elsif parts.size == 2
|
||||
@lang, @region = parts.first.downcase.to_sym, parts.last.upcase.to_sym
|
||||
@full = (parts.first.downcase + '_' + parts.last.upcase).to_sym
|
||||
else
|
||||
raise "malformed language code: #{str}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Persistent
|
||||
attr_reader :lang
|
||||
|
||||
def initialize
|
||||
self.lang = LanguageCode.new(Steam::LANG || Oneshot::LANG)
|
||||
end
|
||||
|
||||
# Members
|
||||
def lang=(val)
|
||||
@lang = val
|
||||
$tr = Translator.new(@lang)
|
||||
$lang = Language.get(@lang)
|
||||
Font.default_name = $lang.font
|
||||
Oneshot.set_yes_no(tr('Yes'), tr('No'))
|
||||
end
|
||||
|
||||
# MARSHAL
|
||||
def marshal_dump
|
||||
[@lang]
|
||||
end
|
||||
def marshal_load(array)
|
||||
self.lang = array.first
|
||||
end
|
||||
|
||||
# Save/Load global instance of persistent
|
||||
FILE_NAME = Oneshot::SAVE_PATH + '/persistent.dat'
|
||||
def self.save
|
||||
File.open(FILE_NAME, 'wb') do |file|
|
||||
Marshal.dump($persistent, file)
|
||||
end
|
||||
end
|
||||
|
||||
def self.load
|
||||
if FileTest.exist?(FILE_NAME)
|
||||
File.open(FILE_NAME, 'rb') do |file|
|
||||
$persistent = Marshal.load(file)
|
||||
end
|
||||
else
|
||||
$persistent = Persistent.new
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,9 +1,7 @@
|
|||
def save_file_name
|
||||
Oneshot::SAVE_PATH + '/save.dat'
|
||||
end
|
||||
SAVE_FILE_NAME = Oneshot::SAVE_PATH + '/save.dat'
|
||||
|
||||
def save
|
||||
File.open(save_file_name, 'wb') do |file|
|
||||
File.open(SAVE_FILE_NAME, 'wb') do |file|
|
||||
# Wrire frame count for measuring play time
|
||||
Marshal.dump(Graphics.frame_count, file)
|
||||
# Increase save count by 1
|
||||
|
|
@ -27,8 +25,8 @@ def save
|
|||
end
|
||||
|
||||
def load
|
||||
return false unless FileTest.exist?(save_file_name)
|
||||
File.open(save_file_name, 'rb') do |file|
|
||||
return false unless FileTest.exist?(SAVE_FILE_NAME)
|
||||
File.open(SAVE_FILE_NAME, 'rb') do |file|
|
||||
# Read frame count for measuring play time
|
||||
Graphics.frame_count = Marshal.load(file)
|
||||
# Read each type of game object
|
||||
|
|
|
|||
|
|
@ -29,8 +29,6 @@ class Scene_Title
|
|||
# Load save game/initialize data
|
||||
$game_temp = Game_Temp.new
|
||||
new_game unless load
|
||||
# Translate database items
|
||||
$tr.translate_database
|
||||
# Make system object
|
||||
$game_system = Game_System.new
|
||||
# Skip title screen if debug mode
|
||||
|
|
|
|||
|
|
@ -96,6 +96,9 @@ Scene_Battle 4
|
|||
Scene_Name
|
||||
Scene_Debug
|
||||
|
||||
# Persistent data
|
||||
Persistent
|
||||
|
||||
# Internationalization
|
||||
i18n_Translator
|
||||
i18n_Language
|
||||
|
|
|
|||
|
|
@ -9,13 +9,16 @@ class Language
|
|||
@character_table_height = character_table_height
|
||||
end
|
||||
|
||||
def self.get(code = :en)
|
||||
return LANGUAGES[code] || LANGUAGES[:en]
|
||||
def self.get(lc)
|
||||
return LANGUAGES[lc.full] || LANGUAGES[lc.lang] || LANGUAGES[:en]
|
||||
end
|
||||
|
||||
FONT_WESTERN = 'Terminus (TTF)'
|
||||
FONT_CJK = 'WenQuanYi Micro Hei'
|
||||
|
||||
LANGUAGES = {
|
||||
:en => Language.new(
|
||||
'Terminus (TTF)', [
|
||||
FONT_WESTERN, [
|
||||
"A","B","C","D","E",
|
||||
"F","G","H","I","J",
|
||||
"K","L","M","N","O",
|
||||
|
|
@ -36,7 +39,7 @@ class Language
|
|||
], 8
|
||||
),
|
||||
:es => Language.new(
|
||||
'Terminus (TTF)', [
|
||||
FONT_WESTERN, [
|
||||
"A","B","C","D","E",
|
||||
"F","G","H","I","J",
|
||||
"K","L","M","N","O",
|
||||
|
|
@ -59,7 +62,7 @@ class Language
|
|||
], 9
|
||||
),
|
||||
:ja => Language.new(
|
||||
'WenQuanYi Micro Hei', [
|
||||
FONT_CJK, [
|
||||
"あ","い","う","え","お",
|
||||
"か","き","く","け","こ",
|
||||
"さ","し","す","せ","そ",
|
||||
|
|
@ -102,7 +105,7 @@ class Language
|
|||
], 9
|
||||
),
|
||||
:ko => Language.new(
|
||||
'WenQuanYi Micro Hei', [
|
||||
FONT_CJK, [
|
||||
"가","개","갸","거","게",
|
||||
"겨","고","교","구","규",
|
||||
"그","기","나","내","냐",
|
||||
|
|
|
|||
|
|
@ -11,14 +11,13 @@ end
|
|||
# Translator class: translate text to another language
|
||||
class Translator
|
||||
# Create Translator object
|
||||
def initialize(code = :en)
|
||||
if code == :en
|
||||
@data = nil
|
||||
else
|
||||
def initialize(lc)
|
||||
@data = nil
|
||||
[lc.full.to_s, lc.lang.to_s].each do |name|
|
||||
begin
|
||||
@data = load_data("Languages/#{code.to_s}.rxdata")
|
||||
@data = load_data("Langauges/#{name}.rxdata")
|
||||
break
|
||||
rescue
|
||||
@data = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -71,10 +70,18 @@ class Translator
|
|||
end
|
||||
end
|
||||
|
||||
# Hacky translation helper function
|
||||
# def tr(text)
|
||||
# $tr.script(Kernel.caller.first.split(':', 3)[1], text)
|
||||
# end
|
||||
def tr(text)
|
||||
text
|
||||
# Translatable string
|
||||
class TrString
|
||||
def initialize(str)
|
||||
@str = str
|
||||
end
|
||||
|
||||
def to_str
|
||||
@str
|
||||
end
|
||||
alias :to_s :to_str
|
||||
end
|
||||
|
||||
def tr(text)
|
||||
TrString.new(text)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -227,7 +227,9 @@ Oneshot::Oneshot(const RGSSThreadData &threadData)
|
|||
//Get language code
|
||||
WCHAR wlang[9];
|
||||
GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, wlang, sizeof(wlang) / sizeof(WCHAR));
|
||||
p->lang = w32_fromWide(wlang);
|
||||
p->lang = w32_fromWide(wlang) + "_";
|
||||
GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SISO3166CTRYNAME, wlang, sizeof(wlang) / sizeof(WCHAR));
|
||||
p->lang += w32_fromWide(wlang);
|
||||
|
||||
//Get user's name
|
||||
ULONG size = 0;
|
||||
|
|
@ -260,9 +262,9 @@ Oneshot::Oneshot(const RGSSThreadData &threadData)
|
|||
const char *code = (lc_all ? lc_all : lang);
|
||||
if (code)
|
||||
{
|
||||
//find first non alphanumeric character, copy language code
|
||||
//find first dot, copy language code
|
||||
int end = 0;
|
||||
for (; code[end] && (code[end] >= 'a' && code[end] <= 'z'); ++end) {}
|
||||
for (; code[end] && code[end] != '.'; ++end) {}
|
||||
p->lang = std::string(code, end);
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -5,6 +5,45 @@
|
|||
#include <SDL2/SDL.h>
|
||||
#include "steamshim/steamshim_child.h"
|
||||
|
||||
/* Language map */
|
||||
static const std::map<std::string, std::string> langToCode = {
|
||||
{"brazilian", "pt_BR"},
|
||||
{"bulgarian", "bg"},
|
||||
{"czech", "cz"},
|
||||
{"danish", "da"},
|
||||
{"dutch", "nl"},
|
||||
{"english", "en"},
|
||||
{"finnish", "fi"},
|
||||
{"french", "fr"},
|
||||
{"german", "de"},
|
||||
{"greek", "el"},
|
||||
{"hungarian", "hu"},
|
||||
{"italian", "it"},
|
||||
{"japanese", "ja"},
|
||||
{"koreana", "ko"},
|
||||
{"korean", "ko"},
|
||||
{"norwegian", "no"},
|
||||
{"polish", "pl"},
|
||||
{"portuguese", "pt"},
|
||||
{"romanian", "ro"},
|
||||
{"russian", "ru"},
|
||||
{"schinese", "zh_CN"},
|
||||
{"spanish", "es"},
|
||||
{"swedish", "sv"},
|
||||
{"tchinese", "zh_TW"},
|
||||
{"thai", "th"},
|
||||
{"turkish", "tr"},
|
||||
{"ukrainian", "uk"},
|
||||
};
|
||||
|
||||
static std::string steamToIsoLang(const char *steamLang)
|
||||
{
|
||||
auto it = langToCode.find(steamLang);
|
||||
if (it != langToCode.end())
|
||||
return it->second;
|
||||
return "en";
|
||||
}
|
||||
|
||||
/* Achievements */
|
||||
static const char *const achievementNames[] = {
|
||||
"SaveWorld",
|
||||
|
|
@ -18,6 +57,7 @@ struct SteamPrivate
|
|||
std::map<std::string, bool> achievements;
|
||||
|
||||
std::string userName;
|
||||
std::string lang;
|
||||
|
||||
SteamPrivate()
|
||||
{
|
||||
|
|
@ -66,6 +106,8 @@ struct SteamPrivate
|
|||
case SHIMEVENT_GETPERSONANAME:
|
||||
userName = e->name;
|
||||
break;
|
||||
case SHIMEVENT_GETCURRENTGAMELANGUAGE:
|
||||
lang = steamToIsoLang(e->name);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -75,6 +117,7 @@ struct SteamPrivate
|
|||
bool initialized()
|
||||
{
|
||||
return !userName.empty()
|
||||
&& !lang.empty()
|
||||
&& achievements.size() == NUM_ACHIEVEMENTS;
|
||||
}
|
||||
};
|
||||
|
|
@ -95,6 +138,11 @@ const std::string &Steam::userName() const
|
|||
return p->userName;
|
||||
}
|
||||
|
||||
const std::string &Steam::lang() const
|
||||
{
|
||||
return p->lang;
|
||||
}
|
||||
|
||||
void Steam::unlock(const char *name)
|
||||
{
|
||||
p->setAchievement(name, true);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ public:
|
|||
bool isUnlocked(const char *name);
|
||||
|
||||
const std::string &userName() const;
|
||||
const std::string &lang() const;
|
||||
|
||||
private:
|
||||
Steam();
|
||||
|
|
|
|||
Loading…
Reference in a new issue