load strings from po file, not xml.

This commit is contained in:
Enno Rehling 2018-05-17 16:54:59 +02:00
parent 9ca945cb2c
commit c596402e4a
5 changed files with 166 additions and 3 deletions

View File

@ -1,8 +1,8 @@
{
"include": [
"config://res/translations/strings.de.po",
"config://res/translations/strings.en.po",
"config://res/core/messages.xml",
"config://res/core/de/strings.xml",
"config://res/core/en/strings.xml",
"config://res/eressea/strings.xml",
"config://res/eressea/spellinfo.xml",
"config://res/names-undead.xml",

View File

@ -126,6 +126,7 @@ set (ERESSEA_SRC
summary.c
travelthru.c
monsters.c
pofile.c
wormhole.c
xmlreader.c
${SPELLS_SRC}

View File

@ -45,6 +45,7 @@ without prior permission by the authors of Eressea.
#include "keyword.h"
#include "move.h"
#include "prefix.h"
#include "pofile.h"
#include "skill.h"
/* external libraries */
@ -1020,6 +1021,40 @@ static int include_xml(const char *uri) {
return err;
}
static int add_po_string(const char *msgid, const char *msgstr, const char *msgctxt, void *data) {
struct locale * lang = (struct locale *)data;
const char * key = msgid;
if (msgctxt) {
key = mkname(msgctxt, msgid);
}
locale_setstring(lang, key, msgstr);
return 0;
}
static int include_po(const char *uri) {
char name[PATH_MAX], lname[8];
const char *filename = uri_to_file(uri, name, sizeof(name));
const char *pos = strstr(filename, ".po");
if (pos) {
const char *str = --pos;
while (str > filename && *str != '.') --str;
if ((pos - str) < sizeof(lname)) {
struct locale * lang;
memcpy(lname, str+1, pos - str);
lname[pos - str] = 0;
lang = get_or_create_locale(lname);
if (lang) {
int err = pofile_read(filename, add_po_string, lang);
if (err < 0) {
log_error("could not parse XML from %s", uri);
}
return err;
}
}
}
return -1;
}
static void json_include(cJSON *json) {
cJSON *child;
if (json->type != cJSON_Array) {
@ -1030,7 +1065,10 @@ static void json_include(cJSON *json) {
const char *uri = child->valuestring;
int err;
if (strstr(uri, ".xml") != NULL) {
if (strstr(uri, ".po") != NULL) {
err = include_po(uri);
}
else if (strstr(uri, ".xml") != NULL) {
err = include_xml(uri);
}
else {

116
src/pofile.c Normal file
View File

@ -0,0 +1,116 @@
#ifdef _MSC_VER
#include <platform.h>
#endif
#include "pofile.h"
#include "util/log.h"
#include "util/strings.h"
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#define MAXLINE 2048
static char po_line[MAXLINE];
static int po_lineno;
char * read_line(FILE *F) {
char * read = fgets(po_line, MAXLINE, F);
++po_lineno;
return read;
}
char * read_multiline(FILE *F, char *line, char *buffer, size_t size) {
char *output = buffer;
while (line) {
size_t len;
char *read = line;
while (read[0] && isspace(read[0])) {
/* eat whitespace */
++read;
}
if (read[0] != '"') {
break;
}
++read;
str_unescape(read);
len = strlen(read);
if (len >= 2) {
/* strip trailing quote (and possible newline) */
if (read[len - 1] == '\n') {
--len;
}
if (read[len - 1] == '"') {
--len;
}
if (size > len) {
/* copy into buffer */
memcpy(output, read, len);
output += len;
size -= len;
output[0] = '\0';
}
}
line = read_line(F);
}
return line;
}
int pofile_read(const char *filename, int (*callback)(const char *msgid, const char *msgstr, const char *msgctxt, void *data), void *data) {
FILE * F = fopen(filename, "rt");
char msgctxt[32];
char msgid[64];
char msgstr[2048];
char *line;
int err = 0;
if (!F) {
log_error("could not open %s", filename);
}
msgctxt[0] = 0;
msgid[0] = 0;
line = read_line(F);
while (line) {
char token[8];
int err = sscanf(line, "%8s", token);
if (err == 1) {
char *text = NULL;
size_t size, len = strlen(token);
line = line + len + 1;
if (len == 7 && memcmp(token, "msgctxt", 7) == 0) {
text = msgctxt;
size = sizeof(msgctxt);
}
else if (len == 5 && memcmp(token, "msgid", 5) == 0) {
text = msgid;
size = sizeof(msgid);
}
else if (len == 6 && memcmp(token, "msgstr", 6) == 0) {
line = read_multiline(F, line, msgstr, sizeof(msgstr));
if (msgid[0]) {
err = callback(msgid, msgstr, msgctxt[0] ? msgctxt : NULL, data);
if (err != 0) {
break;
}
msgctxt[0] = 0;
msgid[0] = 0;
}
}
if (text) {
line = read_multiline(F, line, text, size);
}
}
else {
line = read_line(F);
}
}
if (ferror(F)) {
log_error("read error in %s:%d.", filename, po_lineno);
return -1;
}
fclose(F);
return err;
}

8
src/pofile.h Normal file
View File

@ -0,0 +1,8 @@
#pragma once
#ifndef H_POFILE
#define H_POFILE
int pofile_read(const char *filename, int (*callback)(const char *msgid, const char *msgstr, const char *msgctxt, void *data), void *data);
#endif