Skip to content
Permalink
Browse files

Gettext support!

For starters, the main menu is now translatable.

More strings may be made translatable by including "translations.h",
then surrounding strings to translate with _().
For example: add_msg("my message") becomes add_msg(_("my message")).

Instructions for translating, and maintaining translation files,
can be found in TRANSLATING.md.
  • Loading branch information...
yobbobanana committed Jun 29, 2013
1 parent 5604434 commit 377bac95d8f50c58332924f45b6987b596358cac
Showing with 118 additions and 19 deletions.
  1. +87 −0 TRANSLATING.md
  2. +5 −1 main.cpp
  3. +19 −18 main_menu.cpp
  4. +7 −0 translations.h
@@ -0,0 +1,87 @@
Info on translating Cataclysm-DDA into another language.


TRANSLATORS
===========

If there is already a translation available for your language,
and you just want to update or improve it,
you can edit the .po file for your language,
found inside the "lang/po" subdirectory.

After editing this file,
if you are running the dev version and want to test your changes,
perform step 4 from the maintainers section below.


If there is no translation yet,
the .po file will need to be generated.
You can do this yourself by following the instructions below,
or ask one of the CleverRaven devs to do it for you.

When you are done translating,
submit the changes back to CleverRaven for inclusion in Cataclysm-DDA.


MAINTAINERS
===========


Step 1: Extract the translatable strings
----------------------------------------

First we use "xgettext" to find all the translatable strings in the source code,
and store them in the file "cataclysm-dda.pot",
in the lang/po subdirectory.

This needs to be done every time translatable strings are added or modified.
All of the translations depend on this file.

xgettext -d cataclysm-dda -s -o lang/po/cataclysm-dda.pot --keyword=_ *.cpp
Step 2(a): Initialize each language file
----------------------------------------
If we're starting a new translation from scratch,
we have to initialize the translation file.
In this example the translation is into British English (en_UK).
For other languages change "en_UK" to the relevant language identifier.
msginit -l en_UK.utf8 -o lang/po/en_UK.po -i lang/po/cataclysm-dda.pot
Step 2(b): Update an already existing language file
---------------------------------------------------
If we just want to update a translation,
we'll want to keep all the messages that have already been translated.
In this case we use "msgmerge" in stead of "msginit".
msgmerge -s -U lang/po/en_UK.po lang/po/cataclysm-dda.pot
Step 3: Translate
-----------------
Now open the .po file in your favorite editor and translate!
The lines beginning with "msgid" must be left in the english form,
only the lines beginning with "msgstr" should be translated.
Step 4: Compile the .po file
----------------------------
If it is a new translation,
you will need to create a subdirectory in lang/mo for it,
and then a subdirectory called "LC_MESSAGES" inside that.
For example:
mkdir lang/mo/en_UK/LC_MESSAGES
Now run the "msgfmt" program to compile the translations for use in game.
msgfmt -c -o lang/mo/en_UK/LC_MESSAGES/cataclysm-dda.mo lang/po/en_UK.po
Hooray, that's it :).
@@ -15,6 +15,8 @@
#include <cstdlib>
#include <signal.h>
#include <clocale>
#include <libintl.h>
#include "translations.h"

void exit_handler(int s);

@@ -34,6 +36,8 @@ int main(int argc, char *argv[])

// set locale to system default
setlocale(LC_ALL, "");
bindtextdomain("cataclysm-dda", "lang/mo");
textdomain("cataclysm-dda");

//args: world seeding only.
argc--; argv++;
@@ -104,7 +108,7 @@ void exit_handler(int s) {
bool bExit = false;

if (s == 2) {
if (query_yn("Really Quit? All unsaved changes will be lost.")) {
if (query_yn(_("Really Quit? All unsaved changes will be lost."))) {
bExit = true;
}
} else if (s == -999) {
@@ -5,6 +5,7 @@
#include "mapbuffer.h"
#include "cursesdef.h"
#include "overmapbuffer.h"
#include "translations.h"

#include <sys/stat.h>
#ifdef _MSC_VER
@@ -26,7 +27,7 @@ void game::print_menu(WINDOW* w_open, int iSel, const int iMenuOffsetX, int iMen
for (int i = 1; i < 79; i++)
mvwputch(w_open, 23, i, c_white, LINE_OXOX);

mvwprintz(w_open, 24, 5, c_red, "Please report bugs to TheDarklingWolf@gmail.com or post on the forums.");
mvwprintz(w_open, 24, 5, c_red, _("Please report bugs to TheDarklingWolf@gmail.com or post on the forums."));

int iLine = 0;
const int iOffsetX1 = 3;
@@ -64,15 +65,15 @@ void game::print_menu(WINDOW* w_open, int iSel, const int iMenuOffsetX, int iMen
}

std::vector<std::string> vMenuItems;
vMenuItems.push_back("MOTD");
vMenuItems.push_back("New Game");
vMenuItems.push_back("Load");
vMenuItems.push_back("Reset");
vMenuItems.push_back("Special");
vMenuItems.push_back("Options");
vMenuItems.push_back("Help");
vMenuItems.push_back("Credits");
vMenuItems.push_back("Quit");
vMenuItems.push_back(_("MOTD"));
vMenuItems.push_back(_("New Game"));
vMenuItems.push_back(_("Load"));
vMenuItems.push_back(_("Reset"));
vMenuItems.push_back(_("Special"));
vMenuItems.push_back(_("Options"));
vMenuItems.push_back(_("Help"));
vMenuItems.push_back(_("Credits"));
vMenuItems.push_back(_("Quit"));

print_menu_items(w_open, vMenuItems, iSel, iMenuOffsetY, iMenuOffsetX);

@@ -109,9 +110,9 @@ bool game::opening_screen()
int iMenuOffsetY = 22;

std::vector<std::string> vSubItems;
vSubItems.push_back("Custom Character");
vSubItems.push_back("Preset Character");
vSubItems.push_back("Random Character");
vSubItems.push_back(_("Custom Character"));
vSubItems.push_back(_("Preset Character"));
vSubItems.push_back(_("Random Character"));

print_menu(w_open, 0, iMenuOffsetX, iMenuOffsetY);

@@ -155,7 +156,7 @@ bool game::opening_screen()
std::ifstream motd_file;
motd_file.open("data/motd");
if (!motd_file.is_open())
motd.push_back("No message today.");
motd.push_back(_("No message today."));
else {
while (!motd_file.eof()) {
std::string tmp;
@@ -170,7 +171,7 @@ bool game::opening_screen()
std::ifstream credits_file;
credits_file.open("data/credits");
if (!credits_file.is_open())
credits.push_back("No message today.");
credits.push_back(_("No message today."));
else {
while (!credits_file.eof()) {
std::string tmp;
@@ -305,7 +306,7 @@ bool game::opening_screen()
}
} else if (sel1 == 2) { // Load Character
if (savegames.size() == 0)
mvwprintz(w_open, iMenuOffsetY - 2, 19 + iMenuOffsetX, c_red, "No save games found!");
mvwprintz(w_open, iMenuOffsetY - 2, 19 + iMenuOffsetX, c_red, _("No save games found!"));
else {
for (int i = 0; i < savegames.size(); i++) {
int line = iMenuOffsetY - 2 - i;
@@ -339,7 +340,7 @@ bool game::opening_screen()
}
}
} else if (sel1 == 3) { // Delete world
if (query_yn("Delete the world and all saves?")) {
if (query_yn(_("Delete the world and all saves?"))) {
delete_save();
savegames.clear();
MAPBUFFER.reset();
@@ -386,7 +387,7 @@ bool game::opening_screen()
}
} else if (layer == 3) { // Character Templates
if (templates.size() == 0)
mvwprintz(w_open, iMenuOffsetY-4, iMenuOffsetX+27, c_red, "No templates found!");
mvwprintz(w_open, iMenuOffsetY-4, iMenuOffsetX+27, c_red, _("No templates found!"));
else {
for (int i = 0; i < templates.size(); i++) {
int line = iMenuOffsetY - 4 - i;
@@ -0,0 +1,7 @@
#ifndef _TRANSLATIONS_H_
#define _TRANSLATIONS_H

#include <libintl.h>
#define _(STRING) gettext(STRING)

#endif // _TRANSLATIONS_H_

0 comments on commit 377bac9

Please sign in to comment.
You can’t perform that action at this time.