Add a new way of using the locale kit with static accessors instead of global variables. This has the following consequences :

* Applications don't have to declare BCatalog fCatalog themselves, it's now done automatically
 * Libs and add-ons can be localized just the same way (except static libraries)
For now this new system is yet disabled as I'm looking for some peer review before going on. To enable it you have to define B_TRANSLATE_USE_NEW_MACROS in each file doing catalog access. This will not stay, I'll update the 
other apps to use it.
The linking in jamfiles must be not only with liblocale.so, but also liblocalestub.a. Not sure how to handle this for user-side applications. Libraries are also required to provide a MIME signature to use any catalog.
The locale preflet is updated to the new system (as a test). Othe rapps will follow if everyone is ok with this approach.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37323 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Adrien Destugues 2010-07-01 11:54:09 +00:00
parent 75e7233162
commit 76a4353b79
12 changed files with 162 additions and 22 deletions

View File

@ -456,11 +456,17 @@ if $(HAIKU_SHARED_LIBSUPC++) {
HAIKU_LIBSUPC++ = $(HAIKU_SHARED_LIBSUPC++) ;
}
# network libraries
HAIKU_NETWORK_LIBS = network ;
HAIKU_NETAPI_LIB = bnetapi ;
HAIKU_SELECT_UNAME_ETC_LIB = ; # libroot, against which we link anyway
# locale libraries
HAIKU_LOCALE_LIBS = liblocale.so liblocalestub.a ;
# library and executable glue code
local commonGlueCode =
<src!system!glue>init_term_dyn.o

View File

@ -33,6 +33,8 @@ class BCatalog {
status_t GetLanguage(BString *lang);
status_t GetFingerprint(uint32 *fp);
status_t SetCatalog(const char* signature, uint32 fingerprint);
status_t InitCheck() const;
int32 CountItems() const;
@ -56,6 +58,21 @@ class BCatalog {
extern BCatalog* be_catalog;
extern BCatalog* be_app_catalog;
// Proxy class for handling a "shared object local" catalog.
// This must be included (statically linked) into each shared object needing
// a catalog on its own (application, add-on, library, ...). The shared object
// must also have a mimetype so that the catalog can be identified.
class BCatalogStub {
private:
static BCatalog sCatalog;
static vint32 sCatalogInitOnce;
public:
static BCatalog* GetCatalog();
};
#ifndef B_AVOID_TRANSLATION_MACROS
// macros for easy catalog-access, define B_AVOID_TRANSLATION_MACROS if
// you don't want these:
@ -79,8 +96,24 @@ extern BCatalog* be_app_catalog;
// source-file.
#ifdef B_TRANSLATE_USE_NEW_MACROS
// Translation macros which may be used to shorten translation requests:
#undef B_TRANSLATE
#define B_TRANSLATE(str) \
BCatalogStub::GetCatalog()->GetString((str), B_TRANSLATE_CONTEXT)
#undef B_TRANSLATE_COMMENT
#define B_TRANSLATE_COMMENT(str, cmt) \
BCatalogStub::GetCatalog()->GetString((str), B_TRANSLATE_CONTEXT, (cmt))
#undef B_TRANSLATE_ALL
#define B_TRANSLATE_ALL(str, ctx, cmt) \
BCatalogStub::GetCatalog()->GetString((str), (ctx), (cmt))
#undef B_TRANSLATE_ID
#define B_TRANSLATE_ID(id) \
BCatalogStub::GetCatalog()->GetString((id))
#else
#define B_TRANSLATE(str) \
be_catalog->GetString((str), B_TRANSLATE_CONTEXT)
@ -95,6 +128,7 @@ extern BCatalog* be_app_catalog;
#undef B_TRANSLATE_ID
#define B_TRANSLATE_ID(id) \
be_catalog->GetString((id))
#endif
// Translation markers which can be used to mark static strings/IDs which
// are used as key for translation requests (at other places in the code):

View File

@ -36,6 +36,7 @@ class BLocaleRoster {
// status_t GetCatalog(BLocale *,const char *mimeType, BCatalog *catalog);
// status_t GetCatalog(const char *mimeType, BCatalog *catalog);
// status_t SetCatalog(BLocale *,const char *mimeType, BCatalog *catalog);
BCatalog* GetCatalog(BCatalog* catalog, vint32* catalogInitStatus);
// status_t GetLocaleFor(const char *langCode, const char *countryCode);

View File

@ -102,6 +102,21 @@ BCatalog::GetData(uint32 id, BMessage *msg)
}
status_t
BCatalog::SetCatalog(const char* signature, uint32 fingerprint)
{
// TODO: The previous fCatalog is leaked here. (The whole chain, it
// looks like.) We should take care that internal members are always
// properly maintained.
// No other method should touch fCatalog directly, either (constructor for
// example)
fCatalog
= be_locale_roster->LoadCatalog(signature, NULL, fingerprint);
return B_OK;
}
status_t
BCatalog::GetAppCatalog(BCatalog* catalog)
{
@ -120,14 +135,9 @@ BCatalog::GetAppCatalog(BCatalog* catalog)
BNode appNode(&appInfo.ref);
appNode.ReadAttr(BLocaleRoster::kCatFingerprintAttr, B_UINT32_TYPE, 0,
&fingerprint, sizeof(uint32));
catalog->SetCatalog(sig.String(), fingerprint);
// try to load catalog (with given fingerprint):
// TODO: Not so nice C++ design here, leading to such bugs: The previous
// fCatalog is leaked here. (The whole chain, it looks like.) There should
// be a SetCatalog() method (it can be private), and that should take care
// that internal members are always properly maintained.
catalog->fCatalog
= be_locale_roster->LoadCatalog(sig.String(), NULL, fingerprint);
// load native embedded id-based catalog. If such a catalog exists,
// we can fall back to native strings for id-based access, too.
BCatalogAddOn *embeddedCatalog

View File

@ -0,0 +1,29 @@
/*
* Copyright 2010, Adrien Destugues <pulkomandy@pulkomandy.ath.cx>.
* Distributed under the terms of the MIT License.
*/
#ifndef __CATALOG_STUB_H__
#define __CATALOG_STUB_H__
#define B_TRANSLATE_USE_NEW_MACROS
#include <Catalog.h>
#include <Locale.h>
#include <LocaleRoster.h>
BCatalog BCatalogStub::sCatalog;
vint32 BCatalogStub::sCatalogInitOnce = false;
/* static */ BCatalog*
BCatalogStub::GetCatalog()
{
return be_locale_roster->GetCatalog(&sCatalog, &sCatalogInitOnce);
}
#endif

View File

@ -41,6 +41,10 @@ SharedLibrary liblocale.so
: be $(TARGET_LIBSTDC++) libicu-common.so libicu-i18n.so
;
StaticLibrary liblocalestub.a
: CatalogStub.cpp
;
SEARCH on [ FGristFiles StringForSize.cpp ] += [ FDirName $(HAIKU_TOP) src kits shared ] ;
SEARCH on [ FGristFiles ColorControl.cpp ] += [ FDirName $(HAIKU_TOP) src kits interface ] ;

View File

@ -16,6 +16,7 @@
#include <stdio.h> // for debug only
#include <syslog.h>
#include <AppFileInfo.h>
#include <Autolock.h>
#include <Catalog.h>
#include <Collator.h>
@ -177,8 +178,8 @@ BCatalogAddOnInfo::UnloadIfPossible()
fInstantiateEmbeddedFunc = NULL;
fCreateFunc = NULL;
fLanguagesFunc = NULL;
log_team(LOG_DEBUG, "catalog-add-on %s has been unloaded",
fName.String());
// log_team(LOG_DEBUG, "catalog-add-on %s has been unloaded",
// fName.String());
}
}
@ -364,9 +365,6 @@ RosterData::InitializeCatalogAddOns()
}
}
log_team(LOG_ERR, "Found : %s priority: %d\n",
dent->d_name,priority);
if (priority >= 0) {
// add-ons with priority < 0 will be ignored
BCatalogAddOnInfo* addOnInfo
@ -386,10 +384,6 @@ RosterData::InitializeCatalogAddOns()
for (int32 i=0; i<fCatalogAddOnInfos.CountItems(); ++i) {
BCatalogAddOnInfo *info
= static_cast<BCatalogAddOnInfo*>(fCatalogAddOnInfos.ItemAt(i));
log_team(LOG_INFO,
"roster uses catalog-add-on %s/%s with priority %d",
info->fIsEmbedded ? "(embedded)" : info->fPath.String(),
info->fName.String(), info->fPriority);
}
}
@ -425,10 +419,65 @@ BLocaleRoster::~BLocaleRoster()
}
BCatalog*
BLocaleRoster::GetCatalog(BCatalog* catalog, vint32* catalogInitStatus)
{
// This function is used in the translation macros, so it can't return a
// status_t. Maybe it could throw exceptions ?
if (catalog == NULL) {
log_team(LOG_ERR, "GetCatalog called with a NULL catalog!");
return catalog;
}
if (*catalogInitStatus == true) {
// Catalog already loaded - nothing else to do
return catalog;
}
// figure out image (shared object) from catalog address
image_info info;
int32 cookie = 0;
bool found = false;
while (get_next_image_info(0, &cookie, &info) == B_OK) {
if ((char*)info.data < (char*)catalog && (char*)info.data+info.data_size
> (char*)catalog) {
found = true;
break;
}
}
if (!found) {
log_team(LOG_DEBUG, "Catalog %x doesn't belong to any image !",catalog);
return catalog;
}
// figure out mimetype from image
BFile objectFile(info.name, B_READ_ONLY);
BAppFileInfo objectInfo(&objectFile);
char objectSignature[B_MIME_TYPE_LENGTH];
objectInfo.GetSignature(objectSignature);
// drop supertype from mimetype (should be "application/"):
char* stripSignature = objectSignature;
while(*(stripSignature++)!='/');
log_team(LOG_DEBUG,
"Image %s (address %x) requested catalog with mimetype %s",
info.name, catalog, stripSignature);
// load the catalog for this mimetype and return it to the app
catalog->SetCatalog(stripSignature, 0);
*catalogInitStatus = true;
return catalog;
}
status_t
BLocaleRoster::GetSystemCatalog(BCatalogAddOn **catalog) const
{
if(!catalog)
if (!catalog)
return B_BAD_VALUE;
*catalog = be_locale_roster->LoadCatalog("system");
return B_OK;

View File

@ -10,8 +10,8 @@ Preference Locale :
LocaleWindow.cpp
TimeFormatSettingsView.cpp
: be liblocale.so $(TARGET_LIBSTDC++) $(TARGET_LIBSUPC++) libicu-common.so
libicu-data.so libshared.a
: be $(TARGET_LIBSTDC++) $(TARGET_LIBSUPC++) libicu-common.so
libicu-data.so libshared.a $(HAIKU_LOCALE_LIBS)
: Locale.rdef
;

View File

@ -16,6 +16,7 @@
#include <new>
#define B_TRANSLATE_USE_NEW_MACROS
#include <Bitmap.h>
#include <Country.h>
#include <Catalog.h>

View File

@ -4,6 +4,9 @@
*/
#define B_TRANSLATE_USE_NEW_MACROS
#include "Locale.h"
#include "LocaleWindow.h"
@ -57,7 +60,6 @@ public:
private:
Settings fSettings;
LocaleWindow* fLocaleWindow;
BCatalog fCatalog;
};
@ -140,8 +142,6 @@ LocalePreflet::LocalePreflet()
:
BApplication(kSignature)
{
be_locale->GetAppCatalog(&fCatalog);
fLocaleWindow = new LocaleWindow();
if (fSettings.Message().HasPoint("window_location")) {

View File

@ -5,6 +5,9 @@
*/
#define B_TRANSLATE_USE_NEW_MACROS
#include "Locale.h"
#include "LocaleWindow.h"
#include "LanguageListView.h"

View File

@ -4,6 +4,9 @@
*/
#define B_TRANSLATE_USE_NEW_MACROS
#include "TimeFormatSettingsView.h"
#include <Alert.h>