(svn r17790) -Feature: translatable base sound/graphics set descriptions

replace/41b28d7194a279bdc17475d4fbe2ea6ec885a466
rubidium 15 years ago
parent f7944f5554
commit d5d2354296

@ -31,7 +31,15 @@ shortname = XMPL
; the version of this graphics set (read as single integer)
version = 0
; a fairly short description of the set
; By adding '.<iso code>' you can translate the description.
; Note that OpenTTD first tries the full ISO code, then the first
; two characters and then uses the fallback (no '.<iso code>').
; The ISO code matching is case sensitive!
; So en_US will be used for en_UK if no en_UK translation is added.
; As a result the below example has 'howdie' for en_US and en_UK but
; 'foo' for all other languages.
description = foo
description.en_US = howdie
; palette used by the set; either DOS or Windows
palette = DOS

@ -31,7 +31,15 @@ shortname = XMPL
; the version of this sound set (read as single integer)
version = 0
; a fairly short description of the set
; By adding '.<iso code>' you can translate the description.
; Note that OpenTTD first tries the full ISO code, then the first
; two characters and then uses the fallback (no '.<iso code>').
; The ISO code matching is case sensitive!
; So en_US will be used for en_UK if no en_UK translation is added.
; As a result the below example has 'howdie' for en_US and en_UK but
; 'foo' for all other languages.
description = foo
description.en_US = howdie
; The files section lists the files that replace sprites.
; The file names are case sensitive.

@ -13,6 +13,7 @@
#define BASE_MEDIA_BASE_H
#include "fileio_func.h"
#include "core/smallmap_type.hpp"
/* Forward declare these; can't do 'struct X' in functions as older GCCs barf on that */
struct IniFile;
@ -41,28 +42,35 @@ struct MD5File {
*/
template <class T, size_t Tnum_files>
struct BaseSet {
typedef SmallMap<const char *, const char *> TranslatedStrings;
/** Number of files in this set */
static const size_t NUM_FILES = Tnum_files;
/** Internal names of the files in this set. */
static const char * const *file_names;
const char *name; ///< The name of the base set
const char *description; ///< Description of the base set
uint32 shortname; ///< Four letter short variant of the name
uint32 version; ///< The version of this base set
const char *name; ///< The name of the base set
TranslatedStrings description; ///< Description of the base set
uint32 shortname; ///< Four letter short variant of the name
uint32 version; ///< The version of this base set
MD5File files[NUM_FILES]; ///< All files part of this set
uint found_files; ///< Number of the files that could be found
uint valid_files; ///< Number of the files that could be found and are valid
MD5File files[NUM_FILES]; ///< All files part of this set
uint found_files; ///< Number of the files that could be found
uint valid_files; ///< Number of the files that could be found and are valid
T *next; ///< The next base set in this list
T *next; ///< The next base set in this list
/** Free everything we allocated */
~BaseSet()
{
free((void*)this->name);
free((void*)this->description);
for (TranslatedStrings::iterator iter = this->description.Begin(); iter != this->description.End(); iter++) {
free((void*)iter->first);
free((void*)iter->second);
}
for (uint i = 0; i < NUM_FILES; i++) {
free((void*)this->files[i].filename);
free((void*)this->files[i].missing_warning);
@ -97,6 +105,30 @@ struct BaseSet {
* @return true if loading was successful.
*/
bool FillSetDetails(IniFile *ini, const char *path);
/**
* Get the description for the given ISO code.
* It falls back to the first two characters of the ISO code in case
* no match could be made with the full ISO code. If even then the
* matching fails the default is returned.
* @param isocode the isocode to search for
* @return the description
*/
const char *GetDescription(const char *isocode = NULL) const
{
if (isocode != NULL) {
/* First the full ISO code */
for (TranslatedStrings::const_iterator iter = this->description.Begin(); iter != this->description.End(); iter++) {
if (strcmp(iter->first, isocode) == 0) return iter->second;
}
/* Then the first two characters */
for (TranslatedStrings::const_iterator iter = this->description.Begin(); iter != this->description.End(); iter++) {
if (strncmp(iter->first, isocode, 2) == 0) return iter->second;
}
}
/* Then fall back */
return this->description.Begin()->second;
}
};
/**

@ -40,7 +40,14 @@ bool BaseSet<T, Tnum_files>::FillSetDetails(IniFile *ini, const char *path)
this->name = strdup(item->value);
fetch_metadata("description");
this->description = strdup(item->value);
this->description[strdup("")] = strdup(item->value);
/* Add the translations of the descriptions too. */
for (const IniItem *item = metadata->item; item != NULL; item = item->next) {
if (strncmp("description.", item->name, 12) != 0) continue;
this->description[strdup(item->name + 12)] = strdup(item->value);
}
fetch_metadata("shortname");
for (uint i = 0; item->value[i] != '\0' && i < 4; i++) {
@ -213,7 +220,7 @@ template <class Tbase_set>
{
p += seprintf(p, last, "List of " SET_TYPE " sets:\n");
for (const Tbase_set *s = BaseMedia<Tbase_set>::available_sets; s != NULL; s = s->next) {
p += seprintf(p, last, "%18s: %s", s->name, s->description);
p += seprintf(p, last, "%18s: %s", s->name, s->GetDescription());
int invalid = s->GetNumInvalid();
if (invalid != 0) {
int missing = s->GetNumMissing();

@ -33,6 +33,7 @@ template <typename T, typename U, uint S = 16>
struct SmallMap : SmallVector<SmallPair<T, U>, S> {
typedef ::SmallPair<T, U> Pair;
typedef Pair *iterator;
typedef const Pair *const_iterator;
/** Creates new SmallMap. Data are initialized in SmallVector constructor */
FORCEINLINE SmallMap() { }

@ -218,12 +218,12 @@ struct GameOptionsWindow : Window {
{
switch (widget) {
case GOW_BASE_GRF_DESCRIPTION:
SetDParamStr(0, BaseGraphics::GetUsedSet()->description);
SetDParamStr(0, BaseGraphics::GetUsedSet()->GetDescription(GetCurrentLanguageIsoCode()));
DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_BLACK_RAW_STRING);
break;
case GOW_BASE_SFX_DESCRIPTION:
SetDParamStr(0, BaseSounds::GetUsedSet()->description);
SetDParamStr(0, BaseSounds::GetUsedSet()->GetDescription(GetCurrentLanguageIsoCode()));
DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_BLACK_RAW_STRING);
break;
}
@ -235,7 +235,7 @@ struct GameOptionsWindow : Window {
case GOW_BASE_GRF_DESCRIPTION:
/* Find the biggest description for the default size. */
for (int i = 0; i < BaseGraphics::GetNumSets(); i++) {
SetDParamStr(0, BaseGraphics::GetSet(i)->description);
SetDParamStr(0, BaseGraphics::GetSet(i)->GetDescription(GetCurrentLanguageIsoCode()));
size->height = max(size->height, (uint)GetStringHeight(STR_BLACK_RAW_STRING, size->width));
}
break;
@ -254,7 +254,7 @@ struct GameOptionsWindow : Window {
case GOW_BASE_SFX_DESCRIPTION:
/* Find the biggest description for the default size. */
for (int i = 0; i < BaseSounds::GetNumSets(); i++) {
SetDParamStr(0, BaseSounds::GetSet(i)->description);
SetDParamStr(0, BaseSounds::GetSet(i)->GetDescription(GetCurrentLanguageIsoCode()));
size->height = max(size->height, (uint)GetStringHeight(STR_BLACK_RAW_STRING, size->width));
}
break;

@ -1486,6 +1486,15 @@ void InitializeLanguagePacks()
if (!ReadLanguagePack(chosen_language)) usererror("Can't read language pack '%s'", dl->ent[chosen_language].file);
}
/**
* Get the ISO language code of the currently loaded language.
* @return the ISO code.
*/
const char *GetCurrentLanguageIsoCode()
{
return _langpack->isocode;
}
/**
* Check whether the currently loaded language pack
* uses characters that the currently loaded font

@ -99,6 +99,7 @@ extern DynamicLanguages _dynlang; // defined in strings.cpp
bool ReadLanguagePack(int index);
void InitializeLanguagePacks();
const char *GetCurrentLanguageIsoCode();
int CDECL StringIDSorter(const StringID *a, const StringID *b);

Loading…
Cancel
Save