From 54789082c9aea189e474fc196f7263e6f08a86f1 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Thu, 28 May 2009 17:59:55 -0400 Subject: [PATCH] Enhancement - StringTable integration - StringTable now integrated into Context. - Docs updated for new "locale" configuration variable. - StringTable unit tests implemented. --- doc/man5/taskrc.5 | 7 +++++ html/config.html | 17 +++++++++++ src/Config.cpp | 4 +-- src/StringTable.cpp | 42 +++++++++++++++++++++++---- src/StringTable.h | 2 +- src/sandbox/Context.cpp | 9 ++++-- src/tests/.gitignore | 1 + src/tests/Makefile | 8 ++++-- src/tests/stringtable.t.cpp | 57 +++++++++++++++++++++++++++++++++++++ 9 files changed, 134 insertions(+), 13 deletions(-) create mode 100644 src/tests/stringtable.t.cpp diff --git a/doc/man5/taskrc.5 b/doc/man5/taskrc.5 index 9fc5a50f1..01aeaa51f 100644 --- a/doc/man5/taskrc.5 +++ b/doc/man5/taskrc.5 @@ -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, 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 .B confirmation=yes May be "yes" or "no", and determines whether task will ask for confirmation before deleting a task. diff --git a/html/config.html b/html/config.html index c789f64fc..3cf316f35 100644 --- a/html/config.html +++ b/html/config.html @@ -52,6 +52,23 @@ /Users/paul/.task +
locale
+
+

+ 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'). +

+ +

+ 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. +

+
+
confirmation
May be "yes" or "no", and determines whether task will ask for diff --git a/src/Config.cpp b/src/Config.cpp index aee4287e9..6dcb4c8ba 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -93,7 +93,7 @@ bool Config::load (const std::string& file) while (getline (in, line)) { // Remove comments. - size_type pound = line.find ("#"); + std::string::size_type pound = line.find ("#"); if (pound != std::string::npos) line = line.substr (0, pound); @@ -102,7 +102,7 @@ bool Config::load (const std::string& file) // Skip empty lines. if (line.length () > 0) { - size_type equal = line.find ("="); + std::string::size_type equal = line.find ("="); if (equal != std::string::npos) { std::string key = trim (line.substr (0, equal), " \t"); diff --git a/src/StringTable.cpp b/src/StringTable.cpp index 9dac4626f..4c11db68b 100644 --- a/src/StringTable.cpp +++ b/src/StringTable.cpp @@ -25,7 +25,10 @@ // //////////////////////////////////////////////////////////////////////////////// +#include #include +#include +#include #include "StringTable.h" //////////////////////////////////////////////////////////////////////////////// @@ -58,7 +61,6 @@ StringTable::~StringTable () } //////////////////////////////////////////////////////////////////////////////// -// [data.location] / language . XX // UTF-8 encoding // // 123 This is the string @@ -66,19 +68,47 @@ StringTable::~StringTable () // ... 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. if (mMapping.find (id) != mMapping.end ()) return mMapping[id]; - std::stringstream error; - error << "MISSING " << id; - return error.str (); + return alternate; } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/StringTable.h b/src/StringTable.h index ef0080d97..f5226c3f2 100644 --- a/src/StringTable.h +++ b/src/StringTable.h @@ -39,7 +39,7 @@ public: ~StringTable (); // Destructor void load (const std::string&); - std::string get (int); + std::string get (int, const std::string&); private: std::map mMapping; diff --git a/src/sandbox/Context.cpp b/src/sandbox/Context.cpp index a8095d165..eca52e2aa 100644 --- a/src/sandbox/Context.cpp +++ b/src/sandbox/Context.cpp @@ -95,16 +95,21 @@ void Context::initialize (int argc, char** argv) 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. // init TDB. - std::string location = config.get ("data.location"); std::vector all; split (all, location, ','); foreach (path, all) tdb.location (expandPath (*path)); - // TODO Load appropriate stringtable. // TODO Load pending.data. // TODO Load completed.data. // TODO Load deleted.data. diff --git a/src/tests/.gitignore b/src/tests/.gitignore index d82085aed..d583ecc30 100644 --- a/src/tests/.gitignore +++ b/src/tests/.gitignore @@ -10,3 +10,4 @@ seq.t att.t mod.t record.t +stringtable.t diff --git a/src/tests/Makefile b/src/tests/Makefile index 6e69f9861..6e7f23555 100644 --- a/src/tests/Makefile +++ b/src/tests/Makefile @@ -1,9 +1,10 @@ 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 LFLAGS = -L/usr/local/lib 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) @@ -55,3 +56,6 @@ mod.t: mod.t.o $(OBJECTS) test.o att.t: att.t.o $(OBJECTS) test.o 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 + diff --git a/src/tests/stringtable.t.cpp b/src/tests/stringtable.t.cpp new file mode 100644 index 000000000..4d282d0b4 --- /dev/null +++ b/src/tests/stringtable.t.cpp @@ -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 +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////// +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; +} + +////////////////////////////////////////////////////////////////////////////////