summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Kalnischkies <kalnischkies@gmail.com>2009-11-26 22:23:08 +0100
committerDavid Kalnischkies <kalnischkies@gmail.com>2009-11-26 22:23:08 +0100
commit45df0ad2aab7d019cec855ba2cfe7ecdd0f8c7c8 (patch)
treef18787e135dcd7ea9444f93abc51c2a6516e2f7e
parent32e994d9c891ba379af7b292eeb81b4402d3f2af (diff)
downloadapt-45df0ad2aab7d019cec855ba2cfe7ecdd0f8c7c8.tar.gz
[BREAK] add possibility to download and use multiply
Translation files, configurable with Acquire::Languages accessable with APT::Configuration::getLanguages() and as always with documentation in apt.conf. The commit also includes a very very simple testapp.
-rw-r--r--apt-pkg/aptconfiguration.cc136
-rw-r--r--apt-pkg/aptconfiguration.h27
-rw-r--r--apt-pkg/deb/debindexfile.cc29
-rw-r--r--apt-pkg/deb/debindexfile.h5
-rw-r--r--apt-pkg/deb/deblistparser.cc17
-rw-r--r--apt-pkg/deb/debmetaindex.cc17
-rw-r--r--apt-pkg/deb/debrecords.cc12
-rw-r--r--apt-pkg/indexfile.cc61
-rw-r--r--apt-pkg/pkgcache.cc26
-rw-r--r--debian/changelog2
-rw-r--r--doc/apt.conf.5.xml24
-rw-r--r--doc/examples/configure-index9
-rw-r--r--test/libapt/getlanguages_test.cc91
-rw-r--r--test/libapt/makefile13
14 files changed, 391 insertions, 78 deletions
diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc
index 45ae9bed5..899004d9f 100644
--- a/apt-pkg/aptconfiguration.cc
+++ b/apt-pkg/aptconfiguration.cc
@@ -87,4 +87,140 @@ const Configuration::getCompressionTypes(bool const &Cached) {
return types;
}
/*}}}*/
+// GetLanguages - Return Vector of Language Codes /*{{{*/
+// ---------------------------------------------------------------------
+/* return a vector of language codes in the prefered order.
+ the special word "environment" will be replaced with the long and the short
+ code of the local settings and it will be insured that this will not add
+ duplicates. So in an german local the setting "environment, de_DE, en, de"
+ will result in "de_DE, de, en".
+ The special word "none" is the stopcode for the not-All code vector */
+std::vector<std::string> const Configuration::getLanguages(bool const &All,
+ bool const &Cached, char const * const Locale) {
+ using std::string;
+
+ // The detection is boring and has a lot of cornercases,
+ // so we cache the results to calculated it only once.
+ std::vector<string> static allCodes;
+ std::vector<string> static codes;
+
+ // we have something in the cache
+ if (codes.empty() == false || allCodes.empty() == false) {
+ if (Cached == true) {
+ if(All == true && allCodes.empty() == false)
+ return allCodes;
+ else
+ return codes;
+ } else {
+ allCodes.clear();
+ codes.clear();
+ }
+ }
+
+ // get the environment language code
+ // we extract both, a long and a short code and then we will
+ // check if we actually need both (rare) or if the short is enough
+ string const envMsg = string(Locale == 0 ? std::setlocale(LC_MESSAGES, NULL) : Locale);
+ size_t const lenShort = (envMsg.find('_') != string::npos) ? envMsg.find('_') : 2;
+ size_t const lenLong = (envMsg.find('.') != string::npos) ? envMsg.find('.') : (lenShort + 3);
+
+ string envLong = envMsg.substr(0,lenLong);
+ string const envShort = envLong.substr(0,lenShort);
+ bool envLongIncluded = true, envShortIncluded = false;
+
+ // first cornercase: LANG=C, so we use only "en" Translation
+ if (envLong == "C") {
+ codes.push_back("en");
+ return codes;
+ }
+
+ if (envLong != envShort) {
+ // to save the servers from unneeded queries, we only try also long codes
+ // for languages it is realistic to have a long code translation file...
+ char const *needLong[] = { "cs", "en", "pt", "sv", "zh", NULL };
+ for (char const **l = needLong; *l != NULL; l++)
+ if (envShort.compare(*l) == 0) {
+ envLongIncluded = false;
+ break;
+ }
+ }
+
+ // we don't add the long code, but we allow the user to do so
+ if (envLongIncluded == true)
+ envLong.clear();
+
+ // FIXME: Remove support for the old APT::Acquire::Translation
+ // it was undocumented and so it should be not very widthly used
+ string const oldAcquire = _config->Find("APT::Acquire::Translation","");
+ if (oldAcquire.empty() == false && oldAcquire != "environment") {
+ if (oldAcquire != "none")
+ codes.push_back(oldAcquire);
+ return codes;
+ }
+
+ // Support settings like Acquire::Translation=none on the command line to
+ // override the configuration settings vector of languages.
+ string const forceLang = _config->Find("Acquire::Languages","");
+ if (forceLang.empty() == false) {
+ if (forceLang == "environment") {
+ if (envLongIncluded == false)
+ codes.push_back(envLong);
+ if (envShortIncluded == false)
+ codes.push_back(envShort);
+ return codes;
+ } else if (forceLang != "none")
+ codes.push_back(forceLang);
+ return codes;
+ }
+
+ std::vector<string> const lang = _config->FindVector("Acquire::Languages");
+ // the default setting -> "environment, en"
+ if (lang.empty() == true) {
+ if (envLongIncluded == false)
+ codes.push_back(envLong);
+ if (envShortIncluded == false)
+ codes.push_back(envShort);
+ if (envShort != "en")
+ codes.push_back("en");
+ return codes;
+ }
+
+ // the configs define the order, so add the environment
+ // then needed and ensure the codes are not listed twice.
+ bool noneSeen = false;
+ for (std::vector<string>::const_iterator l = lang.begin();
+ l != lang.end(); l++) {
+ if (*l == "environment") {
+ if (envLongIncluded == true && envShortIncluded == true)
+ continue;
+ if (envLongIncluded == false) {
+ envLongIncluded = true;
+ if (noneSeen == false)
+ codes.push_back(envLong);
+ allCodes.push_back(envLong);
+ }
+ if (envShortIncluded == false) {
+ envShortIncluded = true;
+ if (noneSeen == false)
+ codes.push_back(envShort);
+ allCodes.push_back(envShort);
+ }
+ continue;
+ } else if (*l == "none") {
+ noneSeen = true;
+ continue;
+ } else if ((envLongIncluded == true && *l == envLong) ||
+ (envShortIncluded == true && *l == envShort))
+ continue;
+
+ if (noneSeen == false)
+ codes.push_back(*l);
+ allCodes.push_back(*l);
+ }
+ if (All == true)
+ return allCodes;
+ else
+ return codes;
+}
+ /*}}}*/
}
diff --git a/apt-pkg/aptconfiguration.h b/apt-pkg/aptconfiguration.h
index 6a123adce..f2f04a39b 100644
--- a/apt-pkg/aptconfiguration.h
+++ b/apt-pkg/aptconfiguration.h
@@ -39,6 +39,33 @@ public: /*{{{*/
* \return a vector of (all) Language Codes in the prefered usage order
*/
std::vector<std::string> static const getCompressionTypes(bool const &Cached = true);
+
+ /** \brief Returns a vector of Language Codes
+ *
+ * Languages can be defined with their two or five chars long code.
+ * This methods handles the various ways to set the prefered codes,
+ * honors the environment and ensures that the codes are not listed twice.
+ *
+ * The special word "environment" will be replaced with the long and the short
+ * code of the local settings and it will be insured that this will not add
+ * duplicates. So in an german local the setting "environment, de_DE, en, de"
+ * will result in "de_DE, de, en".
+ *
+ * Another special word is "none" which separates the prefered from all codes
+ * in this setting. So setting and method can be used to get codes the user want
+ * to see or to get all language codes APT (should) have Translations available.
+ *
+ * \param All return all codes or only codes for languages we want to use
+ * \param Cached saves the result so we need to calculated it only once
+ * this parameter should ony be used for testing purposes.
+ * \param Locale don't get the locale from the system but use this one instead
+ * this parameter should ony be used for testing purposes.
+ *
+ * \return a vector of (all) Language Codes in the prefered usage order
+ */
+ std::vector<std::string> static const getLanguages(bool const &All = false,
+ bool const &Cached = true, char const * const Locale = 0);
+
/*}}}*/
};
/*}}}*/
diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc
index ed7633803..5beb83665 100644
--- a/apt-pkg/deb/debindexfile.cc
+++ b/apt-pkg/deb/debindexfile.cc
@@ -319,10 +319,11 @@ pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const
// TranslationsIndex::debTranslationsIndex - Contructor /*{{{*/
// ---------------------------------------------------------------------
/* */
-debTranslationsIndex::debTranslationsIndex(string URI,string Dist,string Section) :
- pkgIndexFile(true), URI(URI), Dist(Dist), Section(Section)
-{
-}
+debTranslationsIndex::debTranslationsIndex(string URI,string Dist,string Section,
+ char const * const Translation) :
+ pkgIndexFile(true), URI(URI), Dist(Dist), Section(Section),
+ Language(Translation)
+{}
/*}}}*/
// TranslationIndex::Trans* - Return the URI to the translation files /*{{{*/
// ---------------------------------------------------------------------
@@ -355,8 +356,8 @@ string debTranslationsIndex::IndexURI(const char *Type) const
bool debTranslationsIndex::GetIndexes(pkgAcquire *Owner) const
{
if (TranslationsAvailable()) {
- string TranslationFile = "Translation-" + LanguageCode();
- new pkgAcqIndexTrans(Owner, IndexURI(LanguageCode().c_str()),
+ string const TranslationFile = string("Translation-").append(Language);
+ new pkgAcqIndexTrans(Owner, IndexURI(Language),
Info(TranslationFile.c_str()),
TranslationFile);
}
@@ -375,7 +376,7 @@ string debTranslationsIndex::Describe(bool Short) const
snprintf(S,sizeof(S),"%s",Info(TranslationFile().c_str()).c_str());
else
snprintf(S,sizeof(S),"%s (%s)",Info(TranslationFile().c_str()).c_str(),
- IndexFile(LanguageCode().c_str()).c_str());
+ IndexFile(Language).c_str());
return S;
}
/*}}}*/
@@ -397,20 +398,20 @@ string debTranslationsIndex::Info(const char *Type) const
return Info;
}
/*}}}*/
-bool debTranslationsIndex::HasPackages() const
+bool debTranslationsIndex::HasPackages() const /*{{{*/
{
if(!TranslationsAvailable())
return false;
- return FileExists(IndexFile(LanguageCode().c_str()));
+ return FileExists(IndexFile(Language));
}
-
+ /*}}}*/
// TranslationsIndex::Exists - Check if the index is available /*{{{*/
// ---------------------------------------------------------------------
/* */
bool debTranslationsIndex::Exists() const
{
- return FileExists(IndexFile(LanguageCode().c_str()));
+ return FileExists(IndexFile(Language));
}
/*}}}*/
// TranslationsIndex::Size - Return the size of the index /*{{{*/
@@ -419,7 +420,7 @@ bool debTranslationsIndex::Exists() const
unsigned long debTranslationsIndex::Size() const
{
struct stat S;
- if (stat(IndexFile(LanguageCode().c_str()).c_str(),&S) != 0)
+ if (stat(IndexFile(Language).c_str(),&S) != 0)
return 0;
return S.st_size;
}
@@ -430,7 +431,7 @@ unsigned long debTranslationsIndex::Size() const
bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
{
// Check the translation file, if in use
- string TranslationFile = IndexFile(LanguageCode().c_str());
+ string TranslationFile = IndexFile(Language);
if (TranslationsAvailable() && FileExists(TranslationFile))
{
FileFd Trans(TranslationFile,FileFd::ReadOnly);
@@ -462,7 +463,7 @@ bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
/* */
pkgCache::PkgFileIterator debTranslationsIndex::FindInCache(pkgCache &Cache) const
{
- string FileName = IndexFile(LanguageCode().c_str());
+ string FileName = IndexFile(Language);
pkgCache::PkgFileIterator File = Cache.FileBegin();
for (; File.end() == false; File++)
diff --git a/apt-pkg/deb/debindexfile.h b/apt-pkg/deb/debindexfile.h
index b0012c96b..c0e8d7d8e 100644
--- a/apt-pkg/deb/debindexfile.h
+++ b/apt-pkg/deb/debindexfile.h
@@ -77,12 +77,13 @@ class debTranslationsIndex : public pkgIndexFile
string URI;
string Dist;
string Section;
+ const char * const Language;
string Info(const char *Type) const;
string IndexFile(const char *Type) const;
string IndexURI(const char *Type) const;
- inline string TranslationFile() const {return "Translation-" + LanguageCode();};
+ inline string TranslationFile() const {return string("Translation-").append(Language);};
public:
@@ -99,7 +100,7 @@ class debTranslationsIndex : public pkgIndexFile
virtual bool Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const;
virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
- debTranslationsIndex(string URI,string Dist,string Section);
+ debTranslationsIndex(string URI,string Dist,string Section, char const * const Language);
};
class debSourcesIndex : public pkgIndexFile
diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc
index 517b771a5..16e6ee332 100644
--- a/apt-pkg/deb/deblistparser.cc
+++ b/apt-pkg/deb/deblistparser.cc
@@ -13,6 +13,7 @@
#include <apt-pkg/deblistparser.h>
#include <apt-pkg/error.h>
#include <apt-pkg/configuration.h>
+#include <apt-pkg/aptconfiguration.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/crc-16.h>
#include <apt-pkg/md5.h>
@@ -129,10 +130,11 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver)
only describe package properties */
string debListParser::Description()
{
- if (DescriptionLanguage().empty())
+ string const lang = DescriptionLanguage();
+ if (lang.empty())
return Section.FindS("Description");
else
- return Section.FindS(("Description-" + pkgIndexFile::LanguageCode()).c_str());
+ return Section.FindS(string("Description-").append(lang).c_str());
}
/*}}}*/
// ListParser::DescriptionLanguage - Return the description lang string /*{{{*/
@@ -142,7 +144,16 @@ string debListParser::Description()
assumed to describe original description. */
string debListParser::DescriptionLanguage()
{
- return Section.FindS("Description").empty() ? pkgIndexFile::LanguageCode() : "";
+ if (Section.FindS("Description").empty() == false)
+ return "";
+
+ std::vector<string> const lang = APT::Configuration::getLanguages();
+ for (std::vector<string>::const_iterator l = lang.begin();
+ l != lang.end(); l++)
+ if (Section.FindS(string("Description-").append(*l).c_str()).empty() == false)
+ return *l;
+
+ return "";
}
/*}}}*/
// ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/
diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc
index f3ab6960c..8f28f053b 100644
--- a/apt-pkg/deb/debmetaindex.cc
+++ b/apt-pkg/deb/debmetaindex.cc
@@ -5,6 +5,7 @@
#include <apt-pkg/strutl.h>
#include <apt-pkg/acquire-item.h>
#include <apt-pkg/configuration.h>
+#include <apt-pkg/aptconfiguration.h>
#include <apt-pkg/error.h>
using namespace std;
@@ -170,13 +171,19 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool GetAll) const
new indexRecords (Dist));
// Queue the translations
+ std::vector<std::string> const lang = APT::Configuration::getLanguages(true);
for (vector<const debSectionEntry *>::const_iterator I = SectionEntries.begin();
I != SectionEntries.end(); I++) {
if((*I)->IsSrc)
continue;
- debTranslationsIndex i = debTranslationsIndex(URI,Dist,(*I)->Section);
- i.GetIndexes(Owner);
+
+ for (vector<string>::const_iterator l = lang.begin();
+ l != lang.end(); l++)
+ {
+ debTranslationsIndex i = debTranslationsIndex(URI,Dist,(*I)->Section,(*l).c_str());
+ i.GetIndexes(Owner);
+ }
}
return true;
@@ -202,6 +209,7 @@ vector <pkgIndexFile *> *debReleaseIndex::GetIndexFiles()
return Indexes;
Indexes = new vector <pkgIndexFile*>;
+ std::vector<std::string> const lang = APT::Configuration::getLanguages(true);
for (vector<const debSectionEntry *>::const_iterator I = SectionEntries.begin();
I != SectionEntries.end(); I++) {
if ((*I)->IsSrc)
@@ -209,7 +217,10 @@ vector <pkgIndexFile *> *debReleaseIndex::GetIndexFiles()
else
{
Indexes->push_back(new debPackagesIndex (URI, Dist, (*I)->Section, IsTrusted()));
- Indexes->push_back(new debTranslationsIndex(URI, Dist, (*I)->Section));
+
+ for (vector<string>::const_iterator l = lang.begin();
+ l != lang.end(); l++)
+ Indexes->push_back(new debTranslationsIndex(URI,Dist,(*I)->Section,(*l).c_str()));
}
}
diff --git a/apt-pkg/deb/debrecords.cc b/apt-pkg/deb/debrecords.cc
index 8ed0bb7eb..5b8538a46 100644
--- a/apt-pkg/deb/debrecords.cc
+++ b/apt-pkg/deb/debrecords.cc
@@ -11,6 +11,7 @@
#include <apt-pkg/debrecords.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/error.h>
+#include <apt-pkg/aptconfiguration.h>
#include <langinfo.h>
/*}}}*/
@@ -109,13 +110,18 @@ string debRecordParser::ShortDesc()
string debRecordParser::LongDesc()
{
string orig, dest;
- char *codeset = nl_langinfo(CODESET);
if (!Section.FindS("Description").empty())
orig = Section.FindS("Description").c_str();
- else
- orig = Section.FindS(("Description-" + pkgIndexFile::LanguageCode()).c_str()).c_str();
+ else
+ {
+ vector<string> const lang = APT::Configuration::getLanguages();
+ for (vector<string>::const_iterator l = lang.begin();
+ orig.empty() && l != lang.end(); l++)
+ orig = Section.FindS(string("Description-").append(*l).c_str());
+ }
+ char const * const codeset = nl_langinfo(CODESET);
if (strcmp(codeset,"UTF-8") != 0) {
UTF8ToCodeset(codeset, orig, &dest);
orig = dest;
diff --git a/apt-pkg/indexfile.cc b/apt-pkg/indexfile.cc
index 08f71feb0..37be87055 100644
--- a/apt-pkg/indexfile.cc
+++ b/apt-pkg/indexfile.cc
@@ -8,9 +8,9 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#include <apt-pkg/configuration.h>
#include <apt-pkg/indexfile.h>
#include <apt-pkg/error.h>
+#include <apt-pkg/aptconfiguration.h>
#include <clocale>
#include <cstring>
@@ -66,28 +66,20 @@ string pkgIndexFile::SourceInfo(pkgSrcRecords::Parser const &Record,
return string();
}
/*}}}*/
-// IndexFile::TranslationsAvailable - Check if will use Translation /*{{{*/
+// IndexFile::TranslationsAvailable - Check if will use Translation /*{{{*/
// ---------------------------------------------------------------------
/* */
-bool pkgIndexFile::TranslationsAvailable()
-{
- const string Translation = _config->Find("APT::Acquire::Translation");
-
- if (Translation.compare("none") != 0)
- return CheckLanguageCode(LanguageCode().c_str());
- else
- return false;
+bool pkgIndexFile::TranslationsAvailable() {
+ return (APT::Configuration::getLanguages().empty() != true);
}
/*}}}*/
-// IndexFile::CheckLanguageCode - Check the Language Code /*{{{*/
+// IndexFile::CheckLanguageCode - Check the Language Code /*{{{*/
// ---------------------------------------------------------------------
-/* */
-/* common cases: de_DE, de_DE@euro, de_DE.UTF-8, de_DE.UTF-8@euro,
- de_DE.ISO8859-1, tig_ER
- more in /etc/gdm/locale.conf
-*/
-
-bool pkgIndexFile::CheckLanguageCode(const char *Lang)
+/* No intern need for this method anymore as the check for correctness
+ is already done in getLanguages(). Note also that this check is
+ rather bad (doesn't take three character like ast into account).
+ TODO: Remove method with next API break */
+__attribute__ ((deprecated)) bool pkgIndexFile::CheckLanguageCode(const char *Lang)
{
if (strlen(Lang) == 2 || (strlen(Lang) == 5 && Lang[2] == '_'))
return true;
@@ -98,31 +90,14 @@ bool pkgIndexFile::CheckLanguageCode(const char *Lang)
return false;
}
/*}}}*/
-// IndexFile::LanguageCode - Return the Language Code /*{{{*/
+// IndexFile::LanguageCode - Return the Language Code /*{{{*/
// ---------------------------------------------------------------------
-/* return the language code */
-string pkgIndexFile::LanguageCode()
-{
- const string Translation = _config->Find("APT::Acquire::Translation");
-
- if (Translation.compare("environment") == 0)
- {
- string lang = std::setlocale(LC_MESSAGES,NULL);
-
- // we have a mapping of the language codes that contains all the language
- // codes that need the country code as well
- // (like pt_BR, pt_PT, sv_SE, zh_*, en_*)
- const char *need_full_langcode[] = { "pt","sv","zh","en", NULL };
- for(const char **s = need_full_langcode;*s != NULL; s++)
- if(lang.find(*s) == 0)
- return lang.substr(0,5);
-
- if(lang.size() > 2)
- return lang.substr(0,2);
- else
- return lang;
- }
- else
- return Translation;
+/* As we have now possibly more than one LanguageCode this method is
+ supersided by a) private classmembers or b) getLanguages().
+ TODO: Remove method with next API break */
+__attribute__ ((deprecated)) string pkgIndexFile::LanguageCode() {
+ if (TranslationsAvailable() == false)
+ return "";
+ return APT::Configuration::getLanguages()[0];
}
/*}}}*/
diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc
index b0ce6e598..997ff51fe 100644
--- a/apt-pkg/pkgcache.cc
+++ b/apt-pkg/pkgcache.cc
@@ -22,11 +22,11 @@
// Include Files /*{{{*/
#include <apt-pkg/pkgcache.h>
#include <apt-pkg/policy.h>
-#include <apt-pkg/indexfile.h>
#include <apt-pkg/version.h>
#include <apt-pkg/error.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/configuration.h>
+#include <apt-pkg/aptconfiguration.h>
#include <apti18n.h>
@@ -674,14 +674,22 @@ string pkgCache::PkgFileIterator::RelStr()
*/
pkgCache::DescIterator pkgCache::VerIterator::TranslatedDescription() const
{
- pkgCache::DescIterator DescDefault = DescriptionList();
- pkgCache::DescIterator Desc = DescDefault;
- for (; Desc.end() == false; Desc++)
- if (pkgIndexFile::LanguageCode() == Desc.LanguageCode())
- break;
- if (Desc.end() == true)
- Desc = DescDefault;
- return Desc;
+ std::vector<string> const lang = APT::Configuration::getLanguages();
+ for (std::vector<string>::const_iterator l = lang.begin();
+ l != lang.end(); l++)
+ {
+ pkgCache::DescIterator DescDefault = DescriptionList();
+ pkgCache::DescIterator Desc = DescDefault;
+
+ for (; Desc.end() == false; Desc++)
+ if (*l == Desc.LanguageCode())
+ break;
+ if (Desc.end() == true)
+ Desc = DescDefault;
+ return Desc;
+ }
+
+ return DescriptionList();
};
/*}}}*/
diff --git a/debian/changelog b/debian/changelog
index 0cfb5ff30..07d9c0303 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -17,6 +17,8 @@ apt (0.7.25) UNRELEASED; urgency=low
Closes: #552606
[ David Kalnischkies ]
+ * [BREAK] add possibility to download and use multiply
+ Translation files, configurable with Acquire::Translation
* apt-pkg/packagemanager.cc:
- better debug output for ImmediateAdd with depth and why
- improve the message shown for failing immediate configuration
diff --git a/doc/apt.conf.5.xml b/doc/apt.conf.5.xml
index d7ad51cfb..777630e14 100644
--- a/doc/apt.conf.5.xml
+++ b/doc/apt.conf.5.xml
@@ -142,7 +142,7 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
<listitem><para>Default release to install packages from if more than one
version available. Contains release name, codename or release version. Examples: 'stable', 'testing', 'unstable', 'lenny', 'squeeze', '4.0', '5.0*'. See also &apt-preferences;.</para></listitem>
</varlistentry>
-
+
<varlistentry><term>Ignore-Hold</term>
<listitem><para>Ignore Held packages; This global option causes the problem resolver to
ignore held packages in its decision making.</para></listitem>
@@ -392,6 +392,27 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
these warnings are most of the time false negatives. Future versions will maybe include a way to
really prefer uncompressed files to support the usage of local mirrors.</para></listitem>
</varlistentry>
+
+ <varlistentry><term>Languages</term>
+ <listitem><para>The Languages subsection controls which <filename>Translation</filename> files are downloaded
+ and in which order APT tries to display the Description-Translations. APT will try to display the first
+ available Description for the Language which is listed at first. Languages can be defined with their
+ short or long Languagecodes. Note that not all archives provide <filename>Translation</filename>
+ files for every Language - especially the long Languagecodes are rare, so please
+ inform you which ones are available before you set here impossible values.</para>
+ <para>The default list includes "environment" and "en". "<literal>environment</literal>" has a special meaning here:
+ It will be replaced at runtime with the languagecodes extracted from the <literal>LC_MESSAGES</literal> enviroment variable.
+ It will also ensure that these codes are not included twice in the list. If <literal>LC_MESSAGES</literal>
+ is set to "C" only the <filename>Translation-en</filename> file (if available) will be used.
+ To force apt to use no Translation file use the setting <literal>Acquire::Languages=none</literal>. "<literal>none</literal>"
+ is another special meaning code which will stop the search for a fitting <filename>Translation</filename> file.
+ This can be used by the system administrator to let APT know that it should download also this files without
+ actually use them if not the environment specifies this languages. So the following example configuration will
+ result in the order "en, de" in an english and in "de, en" in a german localization. Note that "fr" is downloaded,
+ but not used if APT is not used in a french localization, in such an environment the order would be "fr, de, en".
+ <programlisting>Acquire::Languages { "environment"; "de"; "en"; "none"; "fr"; };</programlisting></para></listitem>
+ </varlistentry>
+
</variablelist>
</para>
</refsect1>
@@ -983,6 +1004,7 @@ is commented.
</listitem>
</varlistentry>
-->
+
</variablelist>
</refsect1>
diff --git a/doc/examples/configure-index b/doc/examples/configure-index
index 7e86b3d4a..05826feaa 100644
--- a/doc/examples/configure-index
+++ b/doc/examples/configure-index
@@ -273,6 +273,15 @@ Acquire
Order { "gz"; "lzma"; "bz2"; };
};
+
+ Languages
+ {
+ "environment";
+ "de";
+ "en";
+ "none";
+ "fr";
+ };
};
// Directory layout
diff --git a/test/libapt/getlanguages_test.cc b/test/libapt/getlanguages_test.cc
new file mode 100644
index 000000000..f3629df68
--- /dev/null
+++ b/test/libapt/getlanguages_test.cc
@@ -0,0 +1,91 @@
+#include <apt-pkg/aptconfiguration.h>
+#include <apt-pkg/configuration.h>
+
+#include <assert.h>
+#include <string>
+#include <vector>
+
+#include <iostream>
+
+// simple helper to quickly output a vector of strings
+void dumpVector(std::vector<std::string> vec) {
+ for (std::vector<std::string>::const_iterator v = vec.begin();
+ v != vec.end(); v++)
+ std::cout << *v << std::endl;
+}
+
+int main(int argc,char *argv[])
+{
+ std::vector<std::string> vec = APT::Configuration::getLanguages(false, false, "de_DE.UTF-8");
+ assert(vec.size() == 2);
+ assert(vec[0] == "de");
+ assert(vec[1] == "en");
+
+ // Special: Check if the cache is actually in use
+ vec = APT::Configuration::getLanguages(false, true, "en_GB.UTF-8");
+ assert(vec.size() == 2);
+ assert(vec[0] == "de");
+ assert(vec[1] == "en");
+
+ vec = APT::Configuration::getLanguages(false, false, "en_GB.UTF-8");
+ assert(vec.size() == 2);
+ assert(vec[0] == "en_GB");
+ assert(vec[1] == "en");
+
+ vec = APT::Configuration::getLanguages(false, false, "pt_PR.UTF-8");
+ assert(vec.size() == 3);
+ assert(vec[0] == "pt_PR");
+ assert(vec[1] == "pt");
+ assert(vec[2] == "en");
+
+ vec = APT::Configuration::getLanguages(false, false, "ast_DE.UTF-8"); // bogus, but syntactical correct
+ assert(vec.size() == 2);
+ assert(vec[0] == "ast");
+ assert(vec[1] == "en");
+
+ vec = APT::Configuration::getLanguages(false, false, "C");
+ assert(vec.size() == 1);
+ assert(vec[0] == "en");
+
+ _config->Set("Acquire::Languages::1", "environment");
+ _config->Set("Acquire::Languages::2", "en");
+ vec = APT::Configuration::getLanguages(false, false, "de_DE.UTF-8");
+ assert(vec.size() == 2);
+ assert(vec[0] == "de");
+ assert(vec[1] == "en");
+
+ _config->Set("Acquire::Languages::3", "de");
+ vec = APT::Configuration::getLanguages(false, false, "de_DE.UTF-8");
+ assert(vec.size() == 2);
+ assert(vec[0] == "de");
+ assert(vec[1] == "en");
+
+ _config->Set("Acquire::Languages::1", "none");
+ vec = APT::Configuration::getLanguages(false, false, "de_DE.UTF-8");
+ assert(vec.size() == 0);
+ vec = APT::Configuration::getLanguages(true, false, "de_DE.UTF-8");
+ assert(vec[0] == "en");
+ assert(vec[1] == "de");
+
+ _config->Set("Acquire::Languages::1", "fr");
+ _config->Set("Acquire::Languages", "de_DE");
+ vec = APT::Configuration::getLanguages(false, false, "de_DE.UTF-8");
+ assert(vec.size() == 1);
+ assert(vec[0] == "de_DE");
+
+ _config->Set("Acquire::Languages", "none");
+ vec = APT::Configuration::getLanguages(true, false, "de_DE.UTF-8");
+ assert(vec.size() == 0);
+
+ _config->Set("Acquire::Languages", "");
+ //FIXME: Remove support for this deprecated setting
+ _config->Set("APT::Acquire::Translation", "ast_DE");
+ vec = APT::Configuration::getLanguages(true, false, "de_DE.UTF-8");
+ assert(vec.size() == 1);
+ assert(vec[0] == "ast_DE");
+ _config->Set("APT::Acquire::Translation", "none");
+ vec = APT::Configuration::getLanguages(true, false, "de_DE.UTF-8");
+ assert(vec.size() == 0);
+
+ return 0;
+}
diff --git a/test/libapt/makefile b/test/libapt/makefile
new file mode 100644
index 000000000..f61a95f3d
--- /dev/null
+++ b/test/libapt/makefile
@@ -0,0 +1,13 @@
+# -*- make -*-
+BASE=../..
+SUBDIR=test/libapt
+BASENAME=_libapt_test
+
+# Bring in the default rules
+include ../../buildlib/defaults.mak
+
+# Program for testing getLanguageCode
+PROGRAM = getLanguages${BASENAME}
+SLIBS = -lapt-pkg
+SOURCE = getlanguages_test.cc
+include $(PROGRAM_H)