summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2009-10-17 20:34:09 +0000
committerrubidium <rubidium@openttd.org>2009-10-17 20:34:09 +0000
commitd5d23542960c5c090c4b7593d156a008b3d84914 (patch)
tree6f9b9dea08f72511637e41f43acf6ff6d55ccc73
parentf7944f555441182dc07f30725c9ec8962582418b (diff)
downloadopenttd-d5d23542960c5c090c4b7593d156a008b3d84914.tar.xz
(svn r17790) -Feature: translatable base sound/graphics set descriptions
-rw-r--r--docs/obg_format.txt8
-rw-r--r--docs/obs_format.txt8
-rw-r--r--src/base_media_base.h50
-rw-r--r--src/base_media_func.h11
-rw-r--r--src/core/smallmap_type.hpp1
-rw-r--r--src/settings_gui.cpp8
-rw-r--r--src/strings.cpp9
-rw-r--r--src/strings_func.h1
8 files changed, 81 insertions, 15 deletions
diff --git a/docs/obg_format.txt b/docs/obg_format.txt
index 87fe11a71..9be2883c4 100644
--- a/docs/obg_format.txt
+++ b/docs/obg_format.txt
@@ -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
diff --git a/docs/obs_format.txt b/docs/obs_format.txt
index 7519f1bfe..f18676891 100644
--- a/docs/obs_format.txt
+++ b/docs/obs_format.txt
@@ -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.
diff --git a/src/base_media_base.h b/src/base_media_base.h
index 070a33291..1d52145b9 100644
--- a/src/base_media_base.h
+++ b/src/base_media_base.h
@@ -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;
+ }
};
/**
diff --git a/src/base_media_func.h b/src/base_media_func.h
index 40d154d65..df49f0b1b 100644
--- a/src/base_media_func.h
+++ b/src/base_media_func.h
@@ -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();
diff --git a/src/core/smallmap_type.hpp b/src/core/smallmap_type.hpp
index 68ee4aff5..269950544 100644
--- a/src/core/smallmap_type.hpp
+++ b/src/core/smallmap_type.hpp
@@ -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() { }
diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp
index 3315b6428..fd352c3e3 100644
--- a/src/settings_gui.cpp
+++ b/src/settings_gui.cpp
@@ -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;
diff --git a/src/strings.cpp b/src/strings.cpp
index bfe583148..bb9bacd93 100644
--- a/src/strings.cpp
+++ b/src/strings.cpp
@@ -1487,6 +1487,15 @@ void InitializeLanguagePacks()
}
/**
+ * 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
* does not support. If this is the case an error
diff --git a/src/strings_func.h b/src/strings_func.h
index e4b1cd3bd..e9a22288d 100644
--- a/src/strings_func.h
+++ b/src/strings_func.h
@@ -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);