Enhancement - StringTable integration

- StringTable now integrated into Context.
- Docs updated for new "locale" configuration variable.
- StringTable unit tests implemented.
This commit is contained in:
Paul Beckingham 2009-05-28 17:59:55 -04:00
parent 8627a924f7
commit 54789082c9
9 changed files with 134 additions and 13 deletions

View file

@ -63,6 +63,13 @@ Valid variable names and their default values are:
This is a path to the directory containing all the task files. By default, it is set up to be ~/.task, This is a path to the directory containing all the task files. By default, it is set up to be ~/.task,
for example: /Users/paul/.task for example: /Users/paul/.task
.TP
.B locale=en-US
The locale is a combination of ISO 639-1 language code and ISO 3166 country
code. If not specified, task will assume en-US. If specified, task will locate
the correct file of localized strings and proceed. It is an error to specify a
locale for which there is no strings file.
.TP .TP
.B confirmation=yes .B confirmation=yes
May be "yes" or "no", and determines whether task will ask for confirmation before deleting a task. May be "yes" or "no", and determines whether task will ask for confirmation before deleting a task.

View file

@ -52,6 +52,23 @@
/Users/paul/.task /Users/paul/.task
</dd> </dd>
<dt>locale</dt>
<dd>
<p>
A locale can be specified as a combination of an ISO 639-1
language code (such as 'en'), and an ISO 3166 country code
(such as 'US'), combined in to specify which strings file
to load ('en-US').
</p>
<p>
If a corresponding strings file is found, it will be loaded,
and all subsequent error messages and feedback will be
localized. It is an error to specify a locale without a
corresponding strings file.
</p>
</dd>
<dt>confirmation</dt> <dt>confirmation</dt>
<dd> <dd>
May be "yes" or "no", and determines whether task will ask for May be "yes" or "no", and determines whether task will ask for

View file

@ -93,7 +93,7 @@ bool Config::load (const std::string& file)
while (getline (in, line)) while (getline (in, line))
{ {
// Remove comments. // Remove comments.
size_type pound = line.find ("#"); std::string::size_type pound = line.find ("#");
if (pound != std::string::npos) if (pound != std::string::npos)
line = line.substr (0, pound); line = line.substr (0, pound);
@ -102,7 +102,7 @@ bool Config::load (const std::string& file)
// Skip empty lines. // Skip empty lines.
if (line.length () > 0) if (line.length () > 0)
{ {
size_type equal = line.find ("="); std::string::size_type equal = line.find ("=");
if (equal != std::string::npos) if (equal != std::string::npos)
{ {
std::string key = trim (line.substr (0, equal), " \t"); std::string key = trim (line.substr (0, equal), " \t");

View file

@ -25,7 +25,10 @@
// //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#include <fstream>
#include <sstream> #include <sstream>
#include <text.h>
#include <util.h>
#include "StringTable.h" #include "StringTable.h"
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -58,7 +61,6 @@ StringTable::~StringTable ()
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// [data.location] / language . XX
// UTF-8 encoding // UTF-8 encoding
// //
// 123 This is the string // 123 This is the string
@ -66,19 +68,47 @@ StringTable::~StringTable ()
// ... // ...
void StringTable::load (const std::string& file) void StringTable::load (const std::string& file)
{ {
// TODO Load the specified file. std::ifstream in;
in.open (file.c_str (), std::ifstream::in);
if (in.good ())
{
std::string line;
while (getline (in, line))
{
// Remove comments.
std::string::size_type pound = line.find ("#");
if (pound != std::string::npos)
line = line.substr (0, pound);
line = trim (line, " \t");
// Skip empty lines.
if (line.length () > 0)
{
std::string::size_type equal = line.find (" ");
if (equal != std::string::npos)
{
int key = ::atoi (trim (line.substr (0, equal), " \t").c_str ());
std::string value = trim (line.substr (equal+1, line.length () - equal), " \t");
mMapping[key] = value;
}
}
}
in.close ();
}
else
throw std::string ("Could not read string file '") + file + "'";
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
std::string StringTable::get (int id) std::string StringTable::get (int id, const std::string& alternate)
{ {
// Return the right string. // Return the right string.
if (mMapping.find (id) != mMapping.end ()) if (mMapping.find (id) != mMapping.end ())
return mMapping[id]; return mMapping[id];
std::stringstream error; return alternate;
error << "MISSING " << id;
return error.str ();
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View file

@ -39,7 +39,7 @@ public:
~StringTable (); // Destructor ~StringTable (); // Destructor
void load (const std::string&); void load (const std::string&);
std::string get (int); std::string get (int, const std::string&);
private: private:
std::map <int, std::string> mMapping; std::map <int, std::string> mMapping;

View file

@ -95,16 +95,21 @@ void Context::initialize (int argc, char** argv)
config.set ("color", "off"); config.set ("color", "off");
} }
// Load appropriate stringtable as soon after the config file as possible, to
// allow all subsequent messages to be localizable.
std::string location = expandPath (config.get ("data.location"));
std::string locale = config.get ("locale");
if (locale != "")
stringtable.load (location + "/strings." + locale);
// TODO Handle "--version, -v" right here. // TODO Handle "--version, -v" right here.
// init TDB. // init TDB.
std::string location = config.get ("data.location");
std::vector <std::string> all; std::vector <std::string> all;
split (all, location, ','); split (all, location, ',');
foreach (path, all) foreach (path, all)
tdb.location (expandPath (*path)); tdb.location (expandPath (*path));
// TODO Load appropriate stringtable.
// TODO Load pending.data. // TODO Load pending.data.
// TODO Load completed.data. // TODO Load completed.data.
// TODO Load deleted.data. // TODO Load deleted.data.

View file

@ -10,3 +10,4 @@ seq.t
att.t att.t
mod.t mod.t
record.t record.t
stringtable.t

View file

@ -1,9 +1,10 @@
PROJECT = t.t tdb.t date.t duration.t t.benchmark.t text.t autocomplete.t \ PROJECT = t.t tdb.t date.t duration.t t.benchmark.t text.t autocomplete.t \
parse.t seq.t att.t mod.t # record.t parse.t seq.t att.t mod.t stringtable.t # record.t
CFLAGS = -I. -I.. -Wall -pedantic -ggdb3 -fno-rtti CFLAGS = -I. -I.. -Wall -pedantic -ggdb3 -fno-rtti
LFLAGS = -L/usr/local/lib LFLAGS = -L/usr/local/lib
OBJECTS = ../TDB.o ../T.o ../parse.o ../text.o ../Date.o ../Duration.o \ OBJECTS = ../TDB.o ../T.o ../parse.o ../text.o ../Date.o ../Duration.o \
../util.o ../Config.o ../Sequence.o ../Att.o ../Record.o ../Mod.o ../util.o ../Config.o ../Sequence.o ../Att.o ../Record.o ../Mod.o \
../StringTable.o
all: $(PROJECT) all: $(PROJECT)
@ -55,3 +56,6 @@ mod.t: mod.t.o $(OBJECTS) test.o
att.t: att.t.o $(OBJECTS) test.o att.t: att.t.o $(OBJECTS) test.o
g++ att.t.o $(OBJECTS) test.o $(LFLAGS) -o att.t g++ att.t.o $(OBJECTS) test.o $(LFLAGS) -o att.t
stringtable.t: stringtable.t.o $(OBJECTS) test.o
g++ stringtable.t.o $(OBJECTS) test.o $(LFLAGS) -o stringtable.t

View file

@ -0,0 +1,57 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <unistd.h>
#include <StringTable.h>
#include <util.h>
#include <test.h>
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
UnitTest t (4);
// Create a string file.
std::string file = "./strings.xx-XX";
spit (file, "# comment\n1 found");
t.is (access (file.c_str (), F_OK), 0, "strings.xx-XX created.");
// Load the string file.
StringTable st;
st.load (file);
// Test the object.
t.is (st.get (1, "nope"), "found", "string 1 'found' found");
t.is (st.get (2, "nope"), "nope", "string 2 'nope' defaulted");
// Clean up.
unlink (file.c_str ());
t.is (access (file.c_str (), F_OK), -1, "strings.xx-XX removed.");
return 0;
}
////////////////////////////////////////////////////////////////////////////////