Merge pull request #9 from taedixon/localization

Localize keybindings
This commit is contained in:
GIRakaCHEEZER 2017-07-16 16:54:25 -07:00 committed by GitHub
commit 8b755ed27e
7 changed files with 291 additions and 73 deletions

View file

@ -2,6 +2,7 @@
#include "binding-types.h"
#include "pipe.h"
#include "debugwriter.h"
#include "i18n.h"
#include <SDL.h>
@ -73,9 +74,14 @@ RB_METHOD(journalSet)
// Record message
SDL_LockMutex(mutex);
message_len = strlen(name);
memcpy((char*)message_buffer, name, message_len);
strcpy((char*)message_buffer, name);
if (message_len > 0) {
// in the case where journal is being sent empty string
// do not append the language suffix, because empty string
// is the signifier to terminate the journal
strcpy((char*)message_buffer + message_len, (char*)lang_buffer);
message_len += strlen((char*)lang_buffer);
}
SDL_UnlockMutex(mutex);
#if defined _WIN32
@ -127,6 +133,7 @@ RB_METHOD(journalSetLang)
const char *lang;
rb_get_args(argc, argv, "z", &lang RB_ARG_END);
strcpy((char*)lang_buffer+1, lang);
loadLocale(lang);
return Qnil;
}

View file

@ -156,7 +156,8 @@ HEADERS += \
src/rgssad.h \
src/sdl-util.h \
src/oneshot.h \
src/pipe.h
src/pipe.h \
src/i18n.h
SOURCES += \
src/main.cpp \
@ -197,7 +198,8 @@ SOURCES += \
src/vorbissource.cpp \
src/oneshot.cpp \
src/screen.cpp \
binding-mri/journal-binding.cpp
binding-mri/journal-binding.cpp \
src/i18n.cpp
STEAM {
HEADERS += src/steam.h steamshim/steamshim_child.h

86
src/i18n.cpp Normal file
View file

@ -0,0 +1,86 @@
/*
Really hacked-together naiive implementation of gettext
*/
#include "i18n.h"
#include "debugwriter.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
const char* LOC_HEADER = "ONELOC\x10";
char** strdict = 0;
unsigned int nStr = 0;
int family = LOCALE_FAMILY_LATIN;
int getLocaleFamily() {
Debug() << "Get family:" << family;
return family;
}
const char* findtext(unsigned int msgid, const char* fallback) {
Debug() << "Looking for msg" << msgid << fallback;
if (msgid >= nStr) {
return fallback;
} else {
Debug() << "found" << strdict[msgid];
return strdict[msgid];
}
}
void unloadLocale() {
for (unsigned int i = 0; i < nStr; i++) {
free(strdict[i]);
}
free(strdict);
strdict = 0;
nStr = 0;
}
void _setLocaleFamily(const char* locale) {
if (!strcmp(locale, "ja")
|| !strcmp(locale, "ko")
|| !strcmp(locale, "zh_CN")) {
family = LOCALE_FAMILY_ASIAN;
} else {
family = LOCALE_FAMILY_LATIN;
}
}
void loadLocale(const char* locale) {
Debug() << "Load locale:" << locale;
char pathbuf[100];
FILE* locfile;
char header[8];
unsigned int i;
int strSize = 0;
unloadLocale();
_setLocaleFamily(locale);
sprintf(pathbuf, "Languages/internal/%s.loc", locale);
locfile = fopen(pathbuf, "rb");
if (locfile) {
fread(header, 1, 8, locfile);
if (!strcmp(header, LOC_HEADER)) {
//read number of strs in this file
fread(&nStr, 4, 1, locfile);
strdict = (char**)malloc(sizeof(char*) * nStr);
for (i = 0; i < nStr; i++) {
//read the size of the next string
fread(&strSize, 4, 1, locfile);
strdict[i] = (char*)malloc(strSize+1);
if (strSize > 0) {
//read the contents of the next string
fread(strdict[i], 1, strSize, locfile);
strdict[i][strSize] = 0;
Debug() << "localization #" << i << " : " << strdict[i] << "|" << strSize;
}
strdict[i][strSize] = 0;
}
}
fclose(locfile);
}
}

14
src/i18n.h Normal file
View file

@ -0,0 +1,14 @@
#ifndef I18N_H
#define I18N_H
#include "trstr.h"
void unloadLocale();
void loadLocale(const char* locale);
const char* findtext(unsigned int msgid, const char* fallback);
int getLocaleFamily();
#define LOCALE_FAMILY_LATIN 1
#define LOCALE_FAMILY_ASIAN 2
#endif /* end of include guard: I18N_H */

View file

@ -37,6 +37,7 @@
#include "debugwriter.h"
#include "exception.h"
#include "gl-fun.h"
#include "i18n.h"
#include "binding.h"
@ -359,6 +360,8 @@ int main(int argc, char *argv[])
Debug() << "Shutting down.";
unloadLocale();
alcCloseDevice(alcDev);
SDL_DestroyWindow(win);

View file

@ -34,6 +34,9 @@
#include "etc-internal.h"
#include "util.h"
#include "sharedstate.h"
#include "i18n.h"
#include "debugwriter.h"
#include <algorithm>
#include <assert.h>
@ -45,8 +48,11 @@ const uint8_t cBgDark = 20;
const uint8_t cLine = 0;
const uint8_t cText = 255;
const char *const fontFamily = "Terminus (TTF)";
const uint8_t fontSize = 12;
// const char *const fontFamilyLatin = "Terminus (TTF)";
const char *const fontFamilyLatin = "WenQuanYi Micro Hei";
const uint8_t fontSizeLatin = 12;
const char *const fontFamilyAsian = "WenQuanYi Micro Hei";
const uint8_t fontSizeAsian = 16;
static bool pointInRect(const SDL_Rect &r, int x, int y)
{
@ -55,51 +61,86 @@ static bool pointInRect(const SDL_Rect &r, int x, int y)
typedef SettingsMenuPrivate SMP;
#define BTN_STRING(btn) { Input:: btn, #btn }
#define BTN_STRING(btn, id) { Input:: btn, id, #btn }
struct VButton
{
Input::ButtonCode code;
int trstrId;
const char *str;
} static const vButtons[] =
{
BTN_STRING(Up),
BTN_STRING(Left),
BTN_STRING(Action),
BTN_STRING(Cancel),
BTN_STRING(Menu),
BTN_STRING(L),
BTN_STRING(Up, TRSTR_KEYBIND_UP),
BTN_STRING(Left, TRSTR_KEYBIND_LEFT),
BTN_STRING(Action, TRSTR_KEYBIND_ACTION),
BTN_STRING(Cancel, TRSTR_KEYBIND_CANCEL),
BTN_STRING(Menu, TRSTR_KEYBIND_MENU),
BTN_STRING(L, TRSTR_KEYBIND_L),
BTN_STRING(Down),
BTN_STRING(Right),
BTN_STRING(Run),
BTN_STRING(Deactivate),
BTN_STRING(Items),
BTN_STRING(R),
BTN_STRING(Down, TRSTR_KEYBIND_DOWN),
BTN_STRING(Right, TRSTR_KEYBIND_RIGHT),
BTN_STRING(Run, TRSTR_KEYBIND_RUN),
BTN_STRING(Deactivate, TRSTR_KEYBIND_DEACTIVATE),
BTN_STRING(Items, TRSTR_KEYBIND_ITEMS),
BTN_STRING(R, TRSTR_KEYBIND_R),
};
static elementsN(vButtons);
const char* getButtonName(int buttonId) {
switch (buttonId) {
case 0:
return findtext(TRSTR_KEYBIND_A, "A Button");
break;
case 1:
return findtext(TRSTR_KEYBIND_B, "B Button");
break;
case 2:
return findtext(TRSTR_KEYBIND_X, "X Button");
break;
case 3:
return findtext(TRSTR_KEYBIND_Y, "Y Button");
break;
case 4:
return findtext(TRSTR_KEYBIND_BACK, "Back Button");
break;
case 5:
return findtext(TRSTR_KEYBIND_GUIDE, "Guide Button");
break;
case 6:
return findtext(TRSTR_KEYBIND_START, "Start Button");
break;
case 7:
return findtext(TRSTR_KEYBIND_LSTICK, "Left Stick");
break;
case 8:
return findtext(TRSTR_KEYBIND_RSTICK, "Right Stick");
break;
case 9:
return findtext(TRSTR_KEYBIND_LSHOULDER, "Left Shoulder");
break;
case 10:
return findtext(TRSTR_KEYBIND_RSHOULDER, "Right Shoulder");
break;
case 11:
return findtext(TRSTR_KEYBIND_PADU, "D-Pad (Up)");
break;
case 12:
return findtext(TRSTR_KEYBIND_PADD, "D-Pad (Down)");
break;
case 13:
return findtext(TRSTR_KEYBIND_PADL, "D-Pad (Left)");
break;
case 14:
return findtext(TRSTR_KEYBIND_PADR, "D-Pad (Right)");
break;
default:
return findtext(TRSTR_KEYBIND_UNK, "Unknown key");
}
}
/* Human readable string representation */
std::string sourceDescString(const SourceDesc &src)
{
static const char *const gcButtonNames[SDL_CONTROLLER_BUTTON_MAX] = {
"A Button",
"B Button",
"X Button",
"Y Button",
"Back Button",
"Guide Button",
"Start Button",
"Left Stick",
"Right Stick",
"Left Shoulder",
"Right Shoulder",
"D-Pad (Up)",
"D-Pad (Down)",
"D-Pad (Left)",
"D-Pad (Right)",
};
char buf[128];
char pos;
@ -111,52 +152,55 @@ std::string sourceDescString(const SourceDesc &src)
case Key:
{
if (src.d.scan == SDL_SCANCODE_LSHIFT)
return "Shift";
return findtext(TRSTR_KEYBIND_SHIFT, "Shift");
SDL_Keycode key = SDL_GetKeyFromScancode(src.d.scan);
const char *str = SDL_GetKeyName(key);
if (*str == '\0')
return "Unknown key";
else
return std::string(str) + " Key";
if (*str == '\0') {
return findtext(TRSTR_KEYBIND_UNK, "Unknown key");
} else {
snprintf(buf, sizeof(buf), findtext(TRSTR_KEYBIND_KEYFMT, "%s Key"), str);
return buf;
}
}
case CButton:
snprintf(buf, sizeof(buf), "%s", gcButtonNames[src.d.jb]);
snprintf(buf, sizeof(buf), "%s", getButtonName(src.d.jb));
return buf;
case CAxis:
switch (src.d.ja.axis) {
case SDL_CONTROLLER_AXIS_LEFTX:
if (src.d.ja.dir == Negative)
return "Left Stick (Left)";
return findtext(TRSTR_KEYBIND_LSTICKL, "Left Stick (Left)");
else
return "Left Stick (Right)";
return findtext(TRSTR_KEYBIND_LSTICKR, "Left Stick (Right)");
case SDL_CONTROLLER_AXIS_LEFTY:
if (src.d.ja.dir == Negative)
return "Left Stick (Up)";
return findtext(TRSTR_KEYBIND_LSTICKU, "Left Stick (Up)");
else
return "Left Stick (Down)";
return findtext(TRSTR_KEYBIND_LSTICKD, "Left Stick (Down)");
case SDL_CONTROLLER_AXIS_RIGHTX:
if (src.d.ja.dir == Negative)
return "Right Stick (Left)";
return findtext(TRSTR_KEYBIND_RSTICKL, "Right Stick (Left)");
else
return "Right Stick (Right)";
return findtext(TRSTR_KEYBIND_RSTICKR, "Right Stick (Right)");
case SDL_CONTROLLER_AXIS_RIGHTY:
if (src.d.ja.dir == Negative)
return "Right Stick (Up)";
return findtext(TRSTR_KEYBIND_RSTICKU, "Right Stick (Up)");
else
return "Right Stick (Down)";
return findtext(TRSTR_KEYBIND_RSTICKD, "Right Stick (Down)");
case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
return "Left Trigger";
return findtext(TRSTR_KEYBIND_LTRIGGER, "Left Trigger");
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
return "Right Trigger";
return findtext(TRSTR_KEYBIND_RTRIGGER, "Right Trigger");
}
return "";
case JButton:
snprintf(buf, sizeof(buf), "Joy Button %d", src.d.jb);
snprintf(buf, sizeof(buf),
findtext(TRSTR_KEYBIND_JOYBTTNFMT, "Joy Button %d"), src.d.jb);
return buf;
case JHat:
@ -181,12 +225,12 @@ std::string sourceDescString(const SourceDesc &src)
default:
pos = '-';
}
snprintf(buf, sizeof(buf), "Joy Hat %d:%c",
snprintf(buf, sizeof(buf), findtext(TRSTR_KEYBIND_JOYHATFMT, "Joy Hat %d:%c"),
src.d.jh.hat, pos);
return buf;
case JAxis:
snprintf(buf, sizeof(buf), "Joy Axis %d%c",
snprintf(buf, sizeof(buf), findtext(TRSTR_KEYBIND_JOYAXISFMT, "Joy Axis %d%c"),
src.d.ja.axis, src.d.ja.dir == Negative ? '-' : '+');
return buf;
}
@ -495,10 +539,13 @@ struct SettingsMenuPrivate
int x, int y, int alignW,
Justification just, SDL_Color c, bool bold = false)
{
Debug() << "draw text:" << str;
SDL_Surface *txt = createTextSurface(str, c, bold);
if (txt) {
blitTextSurf(surf, x, y, alignW, txt, just);
SDL_FreeSurface(txt);
}
}
void drawText(SDL_Surface *surf, const char *str,
int x, int y, int alignW,
@ -586,7 +633,9 @@ struct SettingsMenuPrivate
if (state == AwaitingInput)
{
char buf[64];
snprintf(buf, sizeof(buf), "Press key or joystick button for \"%s\"", captureName);
snprintf(buf, sizeof(buf), findtext(TRSTR_KEYBIND_KEYPROMPT,
"Press key or joystick button for \"%s\""),
captureName);
drawOff = Vec2i();
@ -871,7 +920,7 @@ void BindingWidget::drawHandler(SDL_Surface *surf)
p->strokeRectInner(surf, cLine, 0, 0, rect.w, rect.h, 2);
/* Virtual button name */
p->drawText(surf, vb.str, 1, rect.h/2, cellOffX, Center, true);
p->drawText(surf, findtext(vb.trstrId, vb.str), 1, rect.h/2, cellOffX, Center, true);
/* Cell frames */
p->strokeLineV(surf, cLine, cellOffX, 0, rect.h, 2);
@ -1027,13 +1076,18 @@ SettingsMenu::SettingsMenu(RGSSThreadData &rtData)
p->hasFocus = false;
p->destroyReq = false;
p->window = SDL_CreateWindow("Key bindings",
p->window = SDL_CreateWindow(findtext(TRSTR_KEYBIND_TITLE, "Key bindings"),
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
winSize.x, winSize.y, SDL_WINDOW_INPUT_FOCUS);
p->winSurf = SDL_GetWindowSurface(p->window);
p->winID = SDL_GetWindowID(p->window);
p->font = shState->fontState().getFont(fontFamily, fontSize);
if (getLocaleFamily() == LOCALE_FAMILY_ASIAN) {
p->font = shState->fontState().getFont(fontFamilyAsian, fontSizeAsian);
} else {
p->font = shState->fontState().getFont(fontFamilyLatin, fontSizeLatin);
}
p->rgb = p->winSurf->format;
@ -1067,24 +1121,24 @@ SettingsMenu::SettingsMenu(RGSSThreadData &rtData)
IntRect btRects[] =
{
IntRect(16, buttonY, 112, buttonH),
IntRect(winSize.x-16-64*2-8, buttonY, 64, buttonH),
IntRect(winSize.x-16-64, buttonY, 64, buttonH)
IntRect(16, buttonY, 220, buttonH),
IntRect(winSize.x-16-80*2-8, buttonY, 80, buttonH),
IntRect(winSize.x-16-80, buttonY, 80, buttonH)
};
p->buttons.push_back(Button(p, btRects[0], "Reset defaults", &SMP::onResetToDefault));
p->buttons.push_back(Button(p, btRects[1], "Cancel", &SMP::onCancel));
p->buttons.push_back(Button(p, btRects[2], "Accept", &SMP::onAccept));
p->buttons.push_back(Button(p, btRects[0], findtext(TRSTR_KEYBIND_RESET, "Reset defaults"), &SMP::onResetToDefault));
p->buttons.push_back(Button(p, btRects[1], findtext(TRSTR_CANCEL, "Cancel"), &SMP::onCancel));
p->buttons.push_back(Button(p, btRects[2], findtext(TRSTR_ACCEPT, "Accept"), &SMP::onAccept));
for (size_t i = 0; i< p->buttons.size(); ++i)
p->widgets.push_back(&p->buttons[i]);
/* Labels */
const char *info = "Use left click to bind a slot, right click to clear its binding";
p->infoLabel = Label(p, IntRect(16, 16, winSize.x, 16), info, cText, cText, cText);
const char *info = findtext(TRSTR_KEYBIND_INSTRUCT, "Use left click to bind a slot, right click to clear its binding");
p->infoLabel = Label(p, IntRect(16, 16, winSize.x - 32, 16), info, cText, cText, cText);
const char *warn = "Warning: Same physical action bound to multiple slots";
p->dupWarnLabel = Label(p, IntRect(16, 40, winSize.x, 16), warn, 255, 0, 0);
const char *warn = findtext(TRSTR_KEYBIND_CONFLICT, "Warning: Same physical action bound to multiple slots");
p->dupWarnLabel = Label(p, IntRect(16, 40, winSize.x - 32, 16), warn, 255, 0, 0);
p->widgets.push_back(&p->infoLabel);
p->widgets.push_back(&p->dupWarnLabel);

52
src/trstr.h Normal file
View file

@ -0,0 +1,52 @@
#define TRSTR_EMPTY 0
#define TRSTR_JOURNAL_TITLE 1
#define TRSTR_KEYBIND_A 2
#define TRSTR_KEYBIND_B 3
#define TRSTR_KEYBIND_X 4
#define TRSTR_KEYBIND_Y 5
#define TRSTR_KEYBIND_BACK 6
#define TRSTR_KEYBIND_GUIDE 7
#define TRSTR_KEYBIND_START 8
#define TRSTR_KEYBIND_LSTICK 9
#define TRSTR_KEYBIND_RSTICK 10
#define TRSTR_KEYBIND_LSHOULDER 11
#define TRSTR_KEYBIND_RSHOULDER 12
#define TRSTR_KEYBIND_PADU 13
#define TRSTR_KEYBIND_PADD 14
#define TRSTR_KEYBIND_PADL 15
#define TRSTR_KEYBIND_PADR 16
#define TRSTR_KEYBIND_SHIFT 17
#define TRSTR_KEYBIND_UNK 18
#define TRSTR_KEYBIND_KEYFMT 19
#define TRSTR_KEYBIND_LSTICKL 20
#define TRSTR_KEYBIND_LSTICKR 21
#define TRSTR_KEYBIND_LSTICKU 22
#define TRSTR_KEYBIND_LSTICKD 23
#define TRSTR_KEYBIND_RSTICKL 24
#define TRSTR_KEYBIND_RSTICKR 25
#define TRSTR_KEYBIND_RSTICKU 26
#define TRSTR_KEYBIND_RSTICKD 27
#define TRSTR_KEYBIND_LTRIGGER 28
#define TRSTR_KEYBIND_RTRIGGER 29
#define TRSTR_KEYBIND_JOYBTTNFMT 30
#define TRSTR_KEYBIND_JOYHATFMT 31
#define TRSTR_KEYBIND_JOYAXISFMT 32
#define TRSTR_KEYBIND_KEYPROMPT 33
#define TRSTR_KEYBIND_TITLE 34
#define TRSTR_KEYBIND_RESET 35
#define TRSTR_CANCEL 36
#define TRSTR_ACCEPT 37
#define TRSTR_KEYBIND_INSTRUCT 38
#define TRSTR_KEYBIND_CONFLICT 39
#define TRSTR_KEYBIND_UP 40
#define TRSTR_KEYBIND_LEFT 41
#define TRSTR_KEYBIND_ACTION 42
#define TRSTR_KEYBIND_MENU 43
#define TRSTR_KEYBIND_CANCEL 44
#define TRSTR_KEYBIND_L 45
#define TRSTR_KEYBIND_DOWN 46
#define TRSTR_KEYBIND_RIGHT 47
#define TRSTR_KEYBIND_RUN 48
#define TRSTR_KEYBIND_DEACTIVATE 49
#define TRSTR_KEYBIND_ITEMS 50
#define TRSTR_KEYBIND_R 51