diff --git a/ChangeLog b/ChangeLog index a136fd9f3..1508dbabb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2009-02-23 Ludovic Marcotte + + * Updated German translation. Patch from + Alexander Greiner-Baer + * Added Italian translation. Patch from + Marco Lertora + * Combined the various caches and moved the logic + towards the SOGoCache class. Deprecated the + SOGoLDAPUserManagerCleanupInterval defaults. + Now only SOGoCacheCleanupInterval should be used. + 2009-02-19 Francis Lachapelle * UI/Contacts/UIxContactsListView.m ([UIxContactsListView diff --git a/SoObjects/SOGo/LDAPUserManager.h b/SoObjects/SOGo/LDAPUserManager.h index 4a611786d..d62e6d907 100644 --- a/SoObjects/SOGo/LDAPUserManager.h +++ b/SoObjects/SOGo/LDAPUserManager.h @@ -1,6 +1,6 @@ /* LDAPUserManager.h - this file is part of SOGo * - * Copyright (C) 2007 Inverse inc. + * Copyright (C) 2007-2009 Inverse inc. * * Author: Wolfgang Sourdeau * @@ -34,11 +34,9 @@ @interface LDAPUserManager : NSObject { - NSMutableDictionary *sources; - NSMutableDictionary *sourcesMetadata; - NSTimeInterval cleanupInterval; - NSTimer *cleanupTimer; - NSMutableDictionary *users; + @private + NSMutableDictionary *sources; + NSMutableDictionary *sourcesMetadata; } + (id) sharedUserManager; diff --git a/SoObjects/SOGo/LDAPUserManager.m b/SoObjects/SOGo/LDAPUserManager.m index f0f6f7b56..1ccf830b8 100644 --- a/SoObjects/SOGo/LDAPUserManager.m +++ b/SoObjects/SOGo/LDAPUserManager.m @@ -1,6 +1,6 @@ /* LDAPUserManager.m - this file is part of SOGo * - * Copyright (C) 2007-2008 Inverse inc. + * Copyright (C) 2007-2009 Inverse inc. * * Author: Wolfgang Sourdeau * @@ -22,6 +22,7 @@ #import #import +#import #import #import #import @@ -33,6 +34,7 @@ #import "NSArray+Utilities.h" #import "LDAPSource.h" #import "LDAPUserManager.h" +#import "SOGoCache.h" static NSString *defaultMailDomain = nil; static NSString *LDAPContactInfoAttribute = nil; @@ -147,7 +149,6 @@ static NSLock *lock = nil; - (id) init { NSUserDefaults *ud; - NSString *cleanupSetting; if ((self = [super init])) { @@ -155,27 +156,6 @@ static NSLock *lock = nil; sources = nil; sourcesMetadata = nil; - users = [NSMutableDictionary new]; - cleanupSetting - = [ud objectForKey: @"SOGoLDAPUserManagerCleanupInterval"]; - if (cleanupSetting) - cleanupInterval = [cleanupSetting doubleValue]; - else - cleanupInterval = 0.0; - if (cleanupInterval > 0.0) - { - cleanupTimer - = [NSTimer scheduledTimerWithTimeInterval: cleanupInterval - target: self - selector: @selector (_cleanupSources) - userInfo: nil - repeats: YES]; - [self logWithFormat: @"cleanup interval set every %f seconds", - cleanupInterval]; - } - else - [self - logWithFormat: @"no cleanup interval set: memory usage will grow"]; [self _prepareLDAPSourcesWithDefaults: ud]; } @@ -185,7 +165,6 @@ static NSLock *lock = nil; - (void) dealloc { [sources release]; - [users release]; [super dealloc]; } @@ -312,16 +291,15 @@ static NSLock *lock = nil; - (BOOL) checkLogin: (NSString *) login andPassword: (NSString *) password { - BOOL checkOK; - NSDate *cleanupDate; NSMutableDictionary *currentUser; NSString *dictPassword; + BOOL checkOK; #if defined(THREADSAFE) [lock lock]; #endif - currentUser = [users objectForKey: login]; + currentUser = [[SOGoCache sharedCache] userAttributesForLogin: login]; dictPassword = [currentUser objectForKey: @"password"]; if (currentUser && dictPassword) checkOK = ([dictPassword isEqualToString: password]); @@ -331,19 +309,13 @@ static NSLock *lock = nil; if (!currentUser) { currentUser = [NSMutableDictionary dictionary]; - [users setObject: currentUser forKey: login]; + [[SOGoCache sharedCache] cacheAttributes: currentUser forLogin: login]; } [currentUser setObject: password forKey: @"password"]; } else checkOK = NO; - if (cleanupInterval) - { - cleanupDate = [[NSDate date] addTimeInterval: cleanupInterval]; - [currentUser setObject: cleanupDate forKey: @"cleanupDate"]; - } - #if defined(THREADSAFE) [lock unlock]; #endif @@ -422,35 +394,59 @@ static NSLock *lock = nil; [self _fillContactMailRecords: currentUser]; } +// +// We cache here all identities, including those +// associated with email addresses. +// - (void) _retainUser: (NSDictionary *) newUser { - NSString *key; NSEnumerator *emails; - + NSString *key; + #if defined(THREADSAFE) [lock lock]; #endif key = [newUser objectForKey: @"c_uid"]; if (key) - [users setObject: newUser forKey: key]; + [[SOGoCache sharedCache] cacheAttributes: newUser forLogin: key]; emails = [[newUser objectForKey: @"emails"] objectEnumerator]; while ((key = [emails nextObject])) - [users setObject: newUser forKey: key]; + { + [[SOGoCache sharedCache] cacheAttributes: newUser forLogin: key]; + } #if defined(THREADSAFE) [lock unlock]; #endif + + // We propagate the loaded LDAP attributes to other sogod instances + // which will cache them in SOGoCache (excluding for the instance + // that actually posts the notification) + if ([newUser objectForKey: @"c_uid"]) + { + NSMutableDictionary *d; + + d = [NSMutableDictionary dictionary]; + [d setObject: newUser forKey: @"values"]; + [d setObject: [newUser objectForKey: @"c_uid"] + forKey: @"uid"]; + + [[NSDistributedNotificationCenter defaultCenter] + postNotificationName: @"SOGoUserAttributesHaveLoaded" + object: nil + userInfo: d + deliverImmediately: YES]; + } } - (NSDictionary *) contactInfosForUserWithUIDorEmail: (NSString *) uid { NSMutableDictionary *currentUser, *contactInfos; - NSDate *cleanupDate; BOOL newUser; if ([uid length] > 0) { contactInfos = [NSMutableDictionary dictionary]; - currentUser = [users objectForKey: uid]; + currentUser = [[SOGoCache sharedCache] userAttributesForLogin: uid]; #if defined(THREADSAFE) [lock lock]; #endif @@ -475,11 +471,6 @@ static NSLock *lock = nil; } } - if (cleanupInterval && currentUser) - { - cleanupDate = [[NSDate date] addTimeInterval: cleanupInterval]; - [currentUser setObject: cleanupDate forKey: @"cleanupDate"]; - } #if defined(THREADSAFE) [lock unlock]; #endif @@ -583,40 +574,4 @@ static NSLock *lock = nil; matching: filter]; } -- (void) _cleanupSources -{ - NSEnumerator *userIDs; - NSString *currentID; - NSDictionary *currentUser; - NSDate *now; - unsigned int count; - -#if defined(THREADSAFE) - [lock lock]; -#endif - - now = [NSDate date]; - - count = 0; - - userIDs = [[users allKeys] objectEnumerator]; - while ((currentID = [userIDs nextObject])) - { - currentUser = [users objectForKey: currentID]; - if ([now earlierDate: - [currentUser objectForKey: @"cleanupDate"]] == now) - { - [users removeObjectForKey: currentID]; - count++; - } - } - - if (count) - [self logWithFormat: @"cleaned %d users records from cache", count]; - -#if defined(THREADSAFE) - [lock unlock]; -#endif -} - @end diff --git a/SoObjects/SOGo/SOGoCache.h b/SoObjects/SOGo/SOGoCache.h index c195adab4..c95016dfc 100644 --- a/SoObjects/SOGo/SOGoCache.h +++ b/SoObjects/SOGo/SOGoCache.h @@ -1,6 +1,6 @@ /* SOGoCache.h - this file is part of SOGo * - * Copyright (C) 2008 Inverse inc. + * Copyright (C) 2008-2009 Inverse inc. * * Author: Wolfgang Sourdeau * Ludovic Marcotte @@ -54,12 +54,11 @@ - (void) registerUser: (SOGoUser *) user; - (id) userNamed: (NSString *) name; -+ (void) setCachedUserDefaults: (SOGoUserDefaults *) theDefaults - user: (NSString *) login; -+ (NSDictionary *) cachedUserDefaults; -+ (void) setCachedUserSettings: (SOGoUserDefaults *) theSettings - user: (NSString *) login; -+ (NSDictionary *) cachedUserSettings; +- (void) cacheAttributes: (NSDictionary *) theAttributes + forLogin: (NSString *) theLogin; +- (NSMutableDictionary *) userAttributesForLogin: (NSString *) theLogin; +- (SOGoUserDefaults *) userDefaultsForLogin: (NSString *) theLogin; +- (SOGoUserDefaults *) userSettingsForLogin: (NSString *) theLogin; @end diff --git a/SoObjects/SOGo/SOGoCache.m b/SoObjects/SOGo/SOGoCache.m index 1c8fa48c7..faeb8d61f 100644 --- a/SoObjects/SOGo/SOGoCache.m +++ b/SoObjects/SOGo/SOGoCache.m @@ -1,6 +1,6 @@ /* SOGoCache.m - this file is part of SOGo * - * Copyright (C) 2008 Inverse inc. + * Copyright (C) 2008-2009 Inverse inc. * * Author: Wolfgang Sourdeau * Ludovic Marcotte @@ -21,6 +21,24 @@ * Boston, MA 02111-1307, USA. */ +/* + * [ Structure ] + * users: key = user ID value = NSMutableDictionary instance + * value: key = @"user" value = SOGOUser instance + * key = @"cleanupDate" value = NSDate instance + * key = @"defaults" value = SOGoUserDefaults instance + * key = @"settings" value = SOGoUserDefaults instance + * key = @"attributes" value = NSDictionary instance (attributes from LDAP) + * + * [ Workflows - processes A and B ] + * + * A cache user defaults and posts the notification + * B .... + * + * B crashes + * B receives a notificaion update + */ + #import #import #import @@ -42,14 +60,11 @@ // We define the default value for cleaning up cached // users' preferences. This value should be relatively // high to avoid useless database calls. -static NSTimeInterval cleanupInterval = 1800; +static NSTimeInterval cleanupInterval = 300; static NSMutableDictionary *cache = nil; static NSMutableDictionary *users = nil; -static NSMutableDictionary *s_userDefaults = nil; -static NSMutableDictionary *s_userSettings = nil; - static SOGoCache *sharedCache = nil; #if defined(THREADSAFE) @@ -60,11 +75,9 @@ static NSLock *lock; + (void) initialize { - #if defined(THREADSAFE) +#if defined(THREADSAFE) lock = [NSLock new]; #endif - s_userDefaults = [[NSMutableDictionary alloc] init]; - s_userSettings = [[NSMutableDictionary alloc] init]; } + (NSTimeInterval) cleanupInterval @@ -92,7 +105,6 @@ static NSLock *lock; [lock lock]; #endif [cache removeAllObjects]; - [users removeAllObjects]; #if defined(THREADSAFE) [lock unlock]; #endif @@ -108,12 +120,30 @@ static NSLock *lock; users = [[NSMutableDictionary alloc] init]; // We register ourself for notifications + [[NSDistributedNotificationCenter defaultCenter] + addObserver: self + selector: @selector(_userAttributesHaveLoaded:) + name: @"SOGoUserAttributesHaveLoaded" + object: nil]; + + [[NSDistributedNotificationCenter defaultCenter] + addObserver: self + selector: @selector(_userDefaultsHaveLoaded:) + name: @"SOGoUserDefaultsHaveLoaded" + object: nil]; + [[NSDistributedNotificationCenter defaultCenter] addObserver: self selector: @selector(_userDefaultsHaveChanged:) name: @"SOGoUserDefaultsHaveChanged" object: nil]; + [[NSDistributedNotificationCenter defaultCenter] + addObserver: self + selector: @selector(_userSettingsHaveLoaded:) + name: @"SOGoUserSettingsHaveLoaded" + object: nil]; + [[NSDistributedNotificationCenter defaultCenter] addObserver: self selector: @selector(_userSettingsHaveChanged:) @@ -132,7 +162,7 @@ static NSLock *lock; selector: @selector(_cleanupSources) userInfo: nil repeats: YES]; - [self logWithFormat: @"cleanup interval set every %f seconds", + [self logWithFormat: @"Cache cleanup interval set every %f seconds", cleanupInterval]; } @@ -141,10 +171,25 @@ static NSLock *lock; - (void) dealloc { + [[NSDistributedNotificationCenter defaultCenter] + removeObserver: self + name: @"SOGoUserAttributesHaveLoaded" + object: nil]; + + [[NSDistributedNotificationCenter defaultCenter] + removeObserver: self + name: @"SOGoUserDefaultsHaveLoaded" + object: nil]; + [[NSDistributedNotificationCenter defaultCenter] removeObserver: self name: @"SOGoUserDefaultsHaveChanged" object: nil]; + + [[NSDistributedNotificationCenter defaultCenter] + removeObserver: self + name: @"SOGoUserSettingsHaveLoaded" + object: nil]; [[NSDistributedNotificationCenter defaultCenter] removeObserver: self @@ -157,7 +202,7 @@ static NSLock *lock; } - (NSString *) _pathFromObject: (SOGoObject *) container -withName: (NSString *) name + withName: (NSString *) name { NSString *fullPath, *nameInContainer; NSMutableArray *names; @@ -197,14 +242,11 @@ withName: (NSString *) name #endif if (![cache objectForKey: fullPath]) { - // NSLog (@"registering '%@'", fullPath); [cache setObject: object forKey: fullPath]; } #if defined(THREADSAFE) [lock unlock]; #endif - // else - // NSLog (@"'%@' already registered", fullPath); } } @@ -223,11 +265,21 @@ withName: (NSString *) name - (void) registerUser: (SOGoUser *) user { + NSData *cleanupDate; + #if defined(THREADSAFE) [lock lock]; #endif - [users setObject: user - forKey: [user login]]; + + cleanupDate = [[NSDate date] addTimeInterval: [SOGoCache cleanupInterval]]; + + if (![users objectForKey: [user login]]) + [users setObject: [NSMutableDictionary dictionary] forKey: [user login]]; + + [[users objectForKey: [user login]] setObject: user forKey: @"user"]; + [[users objectForKey: [user login]] setObject: [[NSDate date] addTimeInterval: [SOGoCache cleanupInterval]] + forKey: @"cleanupDate"]; + #if defined(THREADSAFE) [lock unlock]; #endif @@ -235,99 +287,184 @@ withName: (NSString *) name - (id) userNamed: (NSString *) name { - return [users objectForKey: name]; + return [[users objectForKey: name] objectForKey: @"user"]; } -+ (NSDictionary *) cachedUserDefaults +- (void) cacheAttributes: (NSDictionary *) theAttributes + forLogin: (NSString *) theLogin { - return s_userDefaults; + if (![users objectForKey: theLogin]) + [users setObject: [NSMutableDictionary dictionary] forKey: theLogin]; + + [[users objectForKey: theLogin] setObject: theAttributes forKey: @"attributes"]; + [[users objectForKey: theLogin] setObject: [[NSDate date] addTimeInterval: [SOGoCache cleanupInterval]] + forKey: @"cleanupDate"]; } -/* defaults */ -+ (void) setCachedUserDefaults: (SOGoUserDefaults *) theDefaults - user: (NSString *) login +- (NSMutableDictionary *) userAttributesForLogin: (NSString *) theLogin { - NSDate *cleanupDate; + return [[users objectForKey: theLogin] objectForKey: @"attributes"]; +} + +- (SOGoUserDefaults *) userDefaultsForLogin: (NSString *) theLogin +{ + return [[users objectForKey: theLogin] objectForKey: @"defaults"]; +} + +- (SOGoUserDefaults *) userSettingsForLogin: (NSString *) theLogin +{ + return [[users objectForKey: theLogin] objectForKey: @"settings"]; +} + +// +// Notification callbacks. +// +- (void) _cacheValues: (NSDictionary *) theValues + login: (NSString *) theLogin + url: (NSString *) theURL + key: (NSString *) theKey +{ + SOGoUserDefaults *defaults; + NSURL *url; #if defined(THREADSAFE) [lock lock]; #endif - cleanupDate = [[NSDate date] addTimeInterval: [SOGoCache cleanupInterval]]; - [s_userDefaults setObject: [NSDictionary dictionaryWithObjectsAndKeys: - theDefaults, @"dictionary", - cleanupDate, @"cleanupDate", nil] - forKey: login]; + url = [[[NSURL alloc] initWithString: theURL] autorelease]; + + defaults = [[[SOGoUserDefaults alloc] initWithTableURL: url + uid: theLogin + fieldName: [NSString stringWithFormat: @"c_%@", theKey]] + autorelease]; + + if (![users objectForKey: theLogin]) + [users setObject: [NSMutableDictionary dictionary] forKey: theLogin]; + + [[users objectForKey: theLogin] setObject: defaults forKey: theKey]; + [[users objectForKey: theLogin] setObject: [[NSDate date] addTimeInterval: [SOGoCache cleanupInterval]] + forKey: @"cleanupDate"]; + + //NSLog(@"\n\n\nCached user %@ for UID: %@\nvalues: %@\n\n", theKey, theLogin, theValues); + #if defined(THREADSAFE) [lock unlock]; #endif } -+ (NSDictionary *) cachedUserSettings +- (void) _userAttributesHaveLoaded: (NSNotification *) theNotification { - return s_userSettings; + NSString *uid; + + uid = [[theNotification userInfo] objectForKey: @"uid"]; + //NSLog(@"Caching user attributes for UID: %@", uid); + if (![self userAttributesForLogin: uid]) + { + NSEnumerator *emails; + NSDictionary *values; + NSString *key; + + if (![users objectForKey: uid]) + [users setObject: [NSMutableDictionary dictionary] forKey: uid]; + + values = [[theNotification userInfo] objectForKey: @"values"]; + [self cacheAttributes: values forLogin: uid]; + + emails = [[values objectForKey: @"emails"] objectEnumerator]; + while ((key = [emails nextObject])) + { + [self cacheAttributes: values forLogin: key]; + } + + [[users objectForKey: uid] setObject: [[NSDate date] addTimeInterval: [SOGoCache cleanupInterval]] + forKey: @"cleanupDate"]; + } } -+ (void) setCachedUserSettings: (SOGoUserDefaults *) theSettings - user: (NSString *) login +- (void) _userDefaultsHaveLoaded: (NSNotification *) theNotification { - NSDate *cleanupDate; - -#if defined(THREADSAFE) - [lock lock]; -#endif - cleanupDate = [[NSDate date] addTimeInterval: [SOGoCache cleanupInterval]]; - [s_userSettings setObject: [NSDictionary dictionaryWithObjectsAndKeys: - theSettings, @"dictionary", - cleanupDate, @"cleanupDate", nil] - forKey: login]; -#if defined(THREADSAFE) - [lock unlock]; -#endif + NSString *uid; + + uid = [[theNotification userInfo] objectForKey: @"uid"]; + //NSLog(@"Loading user defaults for UID: %@", uid); + if (![self userDefaultsForLogin: uid]) + { + [self _cacheValues: [[theNotification userInfo] objectForKey: @"values"] + login: uid + url: [[theNotification userInfo] objectForKey: @"url"] + key: @"defaults"]; + } } - (void) _userDefaultsHaveChanged: (NSNotification *) theNotification { - SOGoUser *user; - NSString *uid; SOGoUserDefaults *defaults; + NSString *uid; uid = [[theNotification userInfo] objectForKey: @"uid"]; - -#if defined(THREADSAFE) - [lock lock]; -#endif - if ((user = [users objectForKey: uid])) + //NSLog(@"Updating user defaults for UID: %@", uid); + defaults = (SOGoUserDefaults *)[self userDefaultsForLogin: uid]; + if (defaults) { - defaults = (SOGoUserDefaults *) [user userDefaults]; +#if defined(THREADSAFE) + [lock lock]; +#endif [defaults setValues: [[theNotification userInfo] objectForKey: @"values"]]; - [SOGoCache setCachedUserDefaults: defaults user: uid]; + [[users objectForKey: uid] setObject: [[NSDate date] addTimeInterval: [SOGoCache cleanupInterval]] + forKey: @"cleanupDate"]; +#if defined(THREADSAFE) + [lock unlock]; +#endif } else { - [s_userDefaults removeObjectForKey: uid]; + [self _cacheValues: [[theNotification userInfo] objectForKey: @"values"] + login: uid + url: [[theNotification userInfo] objectForKey: @"url"] + key: @"defaults"]; + } +} + +- (void) _userSettingsHaveLoaded: (NSNotification *) theNotification +{ + NSString *uid; + + uid = [[theNotification userInfo] objectForKey: @"uid"]; + //NSLog(@"Loading user settings for UID: %@", uid); + if (![self userSettingsForLogin: uid]) + { + [self _cacheValues: [[theNotification userInfo] objectForKey: @"values"] + login: uid + url: [[theNotification userInfo] objectForKey: @"url"] + key: @"settings"]; } -#if defined(THREADSAFE) - [lock unlock]; -#endif } - (void) _userSettingsHaveChanged: (NSNotification *) theNotification { - SOGoUser *user; + SOGoUserDefaults *settings; NSString *uid; - SOGoUserDefaults *settings; - + uid = [[theNotification userInfo] objectForKey: @"uid"]; - - if ((user = [users objectForKey: uid])) + //NSLog(@"Updating user settings for UID: %@", uid); + settings = (SOGoUserDefaults *)[self userSettingsForLogin: uid]; + if (settings) { - settings = (SOGoUserDefaults *) [user userSettings]; +#if defined(THREADSAFE) + [lock lock]; +#endif [settings setValues: [[theNotification userInfo] objectForKey: @"values"]]; - [SOGoCache setCachedUserSettings: settings user: uid]; + [[users objectForKey: uid] setObject: [[NSDate date] addTimeInterval: [SOGoCache cleanupInterval]] + forKey: @"cleanupDate"]; +#if defined(THREADSAFE) + [lock unlock]; +#endif } else { - [s_userSettings removeObjectForKey: uid]; + [self _cacheValues: [[theNotification userInfo] objectForKey: @"values"] + login: uid + url: [[theNotification userInfo] objectForKey: @"url"] + key: @"settings"]; } } @@ -345,40 +482,23 @@ withName: (NSString *) name #endif now = [NSDate date]; - - // We cleanup the user defaults - userIDs = [[s_userDefaults allKeys] objectEnumerator]; - count = 0; - while ((currentID = [userIDs nextObject])) - { - currentEntry = [s_userDefaults objectForKey: currentID]; - - if ([now earlierDate: [currentEntry objectForKey: @"cleanupDate"]] == now) - { - [s_userDefaults removeObjectForKey: currentID]; - count++; - } - } - - if (count) - [self logWithFormat: @"cleaned %d users records from user defaults cache", count]; - // We cleanup the user settings - userIDs = [[s_userSettings allKeys] objectEnumerator]; + // We cleanup the user cache + userIDs = [[users allKeys] objectEnumerator]; count = 0; while ((currentID = [userIDs nextObject])) { - currentEntry = [s_userSettings objectForKey: currentID]; + currentEntry = [users objectForKey: currentID]; if ([now earlierDate: [currentEntry objectForKey: @"cleanupDate"]] == now) { - [s_userSettings removeObjectForKey: currentID]; + [users removeObjectForKey: currentID]; count++; } } if (count) - [self logWithFormat: @"cleaned %d users records from user settings cache", + [self logWithFormat: @"cleaned %d users records from users cache", count]; #if defined(THREADSAFE) diff --git a/SoObjects/SOGo/SOGoUser.h b/SoObjects/SOGo/SOGoUser.h index 8c3dace3e..8f4685be5 100644 --- a/SoObjects/SOGo/SOGoUser.h +++ b/SoObjects/SOGo/SOGoUser.h @@ -85,30 +85,13 @@ extern NSString *SOGoWeekStartFirstFullWeek; - (NSString *) currentPassword; /* properties */ - -// - (NSString *) fullEmail; - -// - (NSString *) primaryEmail; -// - (NSString *) systemEmail; - (NSArray *) allEmails; - - (BOOL) hasEmail: (NSString *) email; - - (NSString *) cn; - (NSURL *) freeBusyURL; - (SOGoDateFormatter *) dateFormatterInContext: (WOContext *) context; -/* shares and identities */ - -// - (NSString *) primaryIMAP4AccountString; - -// - (NSString *) primaryIMAP4AccountString; -// - (NSString *) primaryMailServer; -// - (NSArray *) additionalIMAP4AccountStrings; -// - (NSArray *) additionalEMailAddresses; -// - (NSDictionary *) additionalIMAP4AccountsAndEMails; - /* defaults */ - (NSUserDefaults *) userDefaults; - (NSUserDefaults *) userSettings; diff --git a/SoObjects/SOGo/SOGoUser.m b/SoObjects/SOGo/SOGoUser.m index ddca24ecc..32010cb20 100644 --- a/SoObjects/SOGo/SOGoUser.m +++ b/SoObjects/SOGo/SOGoUser.m @@ -23,11 +23,13 @@ #import #import #import +#import #import #import #import #import #import +#import #import #import #import @@ -330,20 +332,6 @@ _timeValue (NSString *key) } /* properties */ - -// - (NSString *) fullEmail -// { -// return [[LDAPUserManager sharedUserManager] getFullEmailForUID: login]; -// } - -// - (NSString *) primaryEmail -// { -// if (!allEmails) -// [self _fetchAllEmails]; - -// return [allEmails objectAtIndex: 0]; -// } - - (NSArray *) allEmails { if (!allEmails) @@ -415,26 +403,6 @@ _timeValue (NSString *key) @" variable(s) mentionned above are configured"]; } -// - (NSString *) primaryMailServer -// { -// return [[self userManager] getServerForUID: [self login]]; -// } - -// - (NSArray *) additionalIMAP4AccountStrings -// { -// return [[self userManager]getSharedMailboxAccountStringsForUID: [self login]]; -// } - -// - (NSArray *) additionalEMailAddresses -// { -// return [[self userManager] getSharedMailboxEMailsForUID: [self login]]; -// } - -// - (NSDictionary *) additionalIMAP4AccountsAndEMails -// { -// return [[self userManager] getSharedMailboxesAndEMailsForUID: [self login]]; -// } - - (NSURL *) freeBusyURL { return nil; @@ -491,15 +459,16 @@ _timeValue (NSString *key) - (NSUserDefaults *) userDefaults { SOGoUserDefaults *defaults; - NSDictionary *cachedDefaults; - cachedDefaults = [[SOGoCache cachedUserDefaults] objectForKey: login]; - if (cachedDefaults) - defaults = [cachedDefaults objectForKey: @"dictionary"]; - else + defaults = [[SOGoCache sharedCache] userDefaultsForLogin: login]; + + if (!defaults) { + NSMutableDictionary *d; + defaults = [self primaryUserDefaults]; - /* Required parameters for the web interface */ + + // Required parameters for the Web interface if (![[defaults stringForKey: @"ReplyPlacement"] length]) [defaults setObject: defaultReplyPlacement forKey: @"ReplyPlacement"]; if (![[defaults stringForKey: @"SignaturePlacement"] length]) @@ -509,8 +478,22 @@ _timeValue (NSString *key) if (![[defaults stringForKey: @"MessageCheck"] length]) [defaults setObject: defaultMessageCheck forKey: @"MessageCheck"]; - [SOGoCache setCachedUserDefaults: defaults user: login]; + // We propagate the loaded user defaults to other sogod instances + // which will cache them in SOGoCache (including for the instance + // that actually posts the notification) + d = [NSMutableDictionary dictionary]; + [d setObject: [defaults values] forKey: @"values"]; + [d setObject: login forKey: @"uid"]; + [d setObject: [SOGoProfileURL absoluteString] forKey: @"url"]; + + [[NSDistributedNotificationCenter defaultCenter] + postNotificationName: @"SOGoUserDefaultsHaveLoaded" + object: nil + userInfo: d + deliverImmediately: YES]; } + //else + // NSLog(@"User defaults cache hit for %@", login); return (NSUserDefaults *) defaults; } @@ -518,16 +501,31 @@ _timeValue (NSString *key) - (NSUserDefaults *) userSettings { SOGoUserDefaults *settings; - NSDictionary *cachedSettings; - cachedSettings = [[SOGoCache cachedUserSettings] objectForKey: login]; - if (cachedSettings) - settings = [cachedSettings objectForKey: @"dictionary"]; - else + settings = [[SOGoCache sharedCache] userSettingsForLogin: login]; + + if (!settings) { + NSMutableDictionary *d; + settings = [self primaryUserSettings]; - [SOGoCache setCachedUserSettings: settings user: login]; + [settings fetchProfile]; + // We propagate the loaded user settings to other sogod instances + // which will cache them in SOGoCache (including for the instance + // that actually posts the notification) + d = [NSMutableDictionary dictionary]; + [d setObject: [settings values] forKey: @"values"]; + [d setObject: login forKey: @"uid"]; + [d setObject: [SOGoProfileURL absoluteString] forKey: @"url"]; + + [[NSDistributedNotificationCenter defaultCenter] + postNotificationName: @"SOGoUserSettingsHaveLoaded" + object: nil + userInfo: d + deliverImmediately: YES]; } + //else + // NSLog(@"User settings cache hit for %@", login); return (NSUserDefaults *) settings; } diff --git a/SoObjects/SOGo/SOGoUserDefaults.h b/SoObjects/SOGo/SOGoUserDefaults.h index d7fb827e4..16f477a4a 100644 --- a/SoObjects/SOGo/SOGoUserDefaults.h +++ b/SoObjects/SOGo/SOGoUserDefaults.h @@ -1,14 +1,15 @@ /* Copyright (C) 2005 SKYRIX Software AG + Copyright (C) 2008-2009 Inverse inc. - This file is part of OpenGroupware.org. + This file is part of SOGo. - OGo is free software; you can redistribute it and/or modify it under + SOGo is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - OGo is distributed in the hope that it will be useful, but WITHOUT ANY + SOGo 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 Lesser General Public License for more details. @@ -46,7 +47,6 @@ { int modified: 1; int isNew: 1; - int reserved: 30; } defFlags; } @@ -56,6 +56,7 @@ /* value access */ - (void) setValues: (NSDictionary *) theValues; +- (NSDictionary *) values; - (void) setObject: (id) value forKey: (NSString *) key; diff --git a/SoObjects/SOGo/SOGoUserDefaults.m b/SoObjects/SOGo/SOGoUserDefaults.m index 79b9860d5..ea9350b5c 100644 --- a/SoObjects/SOGo/SOGoUserDefaults.m +++ b/SoObjects/SOGo/SOGoUserDefaults.m @@ -1,15 +1,15 @@ /* Copyright (C) 2005 SKYRIX Software AG - Copyright (C) 2008 Inverse inc. + Copyright (C) 2008-2009 Inverse inc. - This file is part of OpenGroupware.org. + This file is part of SOGo. - OGo is free software; you can redistribute it and/or modify it under + SOGo is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - OGo is distributed in the hope that it will be useful, but WITHOUT ANY + SOGo 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 Lesser General Public License for more details. @@ -159,7 +159,7 @@ static NSString *uidColumnName = @"c_uid"; else values = [NSMutableDictionary new]; - ASSIGN (lastFetch, [NSCalendarDate date]); + ASSIGN(lastFetch, [NSCalendarDate date]); defFlags.modified = NO; rc = YES; } @@ -292,6 +292,7 @@ static NSString *uidColumnName = @"c_uid"; d = [NSMutableDictionary dictionary]; [d setObject: values forKey: @"values"]; [d setObject: uid forKey: @"uid"]; + [d setObject: [url absoluteString] forKey: @"url"]; [[NSDistributedNotificationCenter defaultCenter] postNotificationName: ([fieldName isEqualToString: @"c_defaults"] @@ -322,6 +323,14 @@ static NSString *uidColumnName = @"c_uid"; { [values removeAllObjects]; [values addEntriesFromDictionary: theValues]; + ASSIGN(lastFetch, [NSCalendarDate date]); + defFlags.modified = NO; + defFlags.isNew = NO; +} + +- (NSDictionary *) values +{ + return values; } - (void) setObject: (id) value diff --git a/UI/Common/Italian.lproj/Localizable.strings b/UI/Common/Italian.lproj/Localizable.strings index 0728896a1..23143a2a8 100644 --- a/UI/Common/Italian.lproj/Localizable.strings +++ b/UI/Common/Italian.lproj/Localizable.strings @@ -37,6 +37,6 @@ "The user rights cannot be edited for this object!" = "I permessi di questo oggetto non possono essere modificati!"; "You are not allowed to access this module or this system. Please contact your system administrator." -= "You are not allowed to access this module or this system. Please contact your system administrator."; += "Non sei abilitato ad accedere a questo modulo. Contatta il tuo amministratore di sistema."; "You don't have the required privileges to perform the operation." -= "You don't have the required privileges to perform the operation."; += "Non disponi dei privilegi richiesti per eseguire questa operazione."; diff --git a/UI/Contacts/German.lproj/Localizable.strings b/UI/Contacts/German.lproj/Localizable.strings index 19d1a6123..a9a1bddb9 100644 --- a/UI/Contacts/German.lproj/Localizable.strings +++ b/UI/Contacts/German.lproj/Localizable.strings @@ -67,7 +67,7 @@ "Remove" = "Löschen"; "Please wait..." = "Bitte warten..."; -"No possible subscription" = "Kein abonnieren möglich"; +"No possible subscription" = "Kein Abonnieren möglich"; "Preferred" = "Bevorzugt"; "Card for %@" = "%@"; @@ -114,22 +114,22 @@ "Blind Carbon Copy" = "Blindkopie"; "New Addressbook..." = "Neues Adressbuch..."; -"Subscribe to an Addressbook..." = "Abonnieren..."; -"Remove the selected Addressbook" = "Adressbuch löschen"; +"Subscribe to an Addressbook..." = "Ein Adressbuch abonnieren..."; +"Remove the selected Addressbook" = "Gewähltes Adressbuch löschen"; "Name of the Address Book" = "Adressbuch-Name"; "Are you sure you want to delete the selected address book?" -= "Wollen Sie wirklich das ausgewählte Adressbuch löschen?"; += "Wollen Sie wirklich das gewählte Adressbuch löschen?"; "You cannot remove nor unsubscribe from a public addressbook." = "Sie können das gemeinsame Adressbuch nicht löschen."; "You cannot remove nor unsubscribe from your personal addressbook." = "Sie können ihr Persönliches Adressbuch nicht löschen."; "Are you sure you want to delete the selected contacts?" -= "Wollen Sie wirklich die ausgewählte Karten löschen?"; += "Wollen Sie wirklich die gewählten Karten löschen?"; "You cannot delete the selected contact(s)" -= "Ausgewählte Karten können nicht gelöscht werden."; += "Gewählte Karten können nicht gelöscht werden."; "You cannot delete the card of \"%{0}\"." = "Sie können die Karte von \"%{0}\" nicht löschen."; @@ -140,7 +140,7 @@ "Unable to subscribe to that folder!" = "Abonnieren des Ordners nicht möglich!"; -"Default Roles" = "Standard-Rollen"; +"Default Roles" = "Standardrechte"; "User rights for:" = "Benutzerrechte für:"; "This person can add cards to this addressbook." @@ -152,7 +152,7 @@ "This person can read the cards of this addressbook." = "Diese Person kann Karten dieses Adressbuches anzeigen."; "This person can erase cards from this addressbook." -= "Diese Person kann Karten aus diesem Adressbuch löschen"; += "Diese Person kann Karten aus diesem Adressbuch löschen."; "The selected contact has no email address." = "Der gewählte Kontakt hat keine E-Mail-Adresse."; @@ -163,8 +163,8 @@ "SoAccessDeniedException" = "Sie können nicht auf dieses Adressbuch schreiben."; "Forbidden" = "Sie können nicht auf dieses Adressbuch schreiben."; -"Invalid Contact" = "Der ausgewählte Kontakt existiert nicht mehr."; -"Unknown Destination Folder" = "Das ausgewählte Ziel-Adressbuch existiert nicht mehr."; +"Invalid Contact" = "Der gewählte Kontakt existiert nicht mehr."; +"Unknown Destination Folder" = "Das gewählte Ziel-Adressbuch existiert nicht mehr."; "Move To" = "Verschieben in"; "Copy To" = "Kopieren in"; diff --git a/UI/Contacts/Italian.lproj/Localizable.strings b/UI/Contacts/Italian.lproj/Localizable.strings index 40bfc5285..3ac209783 100644 --- a/UI/Contacts/Italian.lproj/Localizable.strings +++ b/UI/Contacts/Italian.lproj/Localizable.strings @@ -15,7 +15,7 @@ "Addressbook" = "Rubrica"; "Addresses" = "Indirizzi"; "Update" = "Aggiorna"; -"Cancel" = "Anulla"; +"Cancel" = "Annulla"; "Common" = "Comuni"; "Contact editor" = "Editor dei contatti"; "Contact viewer" = "Visulizzatore dei contatti"; @@ -42,7 +42,7 @@ "delete" = "cancella"; "edit" = "modifica"; "invalidemailwarn" = "L'indirizzo email specificato non è valido"; -"new" = "new"; +"new" = "nuovo"; "Preferred Phone" = "Telefono lavoro"; /* Tooltips */ @@ -71,8 +71,8 @@ "Add..." = "Aggiungi..."; "Remove" = "Rimuovi"; -"Please wait..." = "Please wait..."; -"No possible subscription" = "No possible subscription"; +"Please wait..." = "Attendere prego..."; +"No possible subscription" = "Nessuna sottoscrizione possibile"; "Preferred" = "Predefinito"; "Card for %@" = "Biglietto da visita di %@"; @@ -125,6 +125,9 @@ "Carbon Copy" = "Copia Carbone"; "Blind Carbon Copy" = "Copia Carbone Nascosta"; +"Move To" = "Sposta in "; +"Copy To" = "Copia in "; + "New Addressbook..." = "Nuova rubrica..."; "Subscribe to an Addressbook..." = "Sottoscrivi una rubrica..."; "Remove the selected Addressbook" = "Rimuovi la rubrica selezionata"; @@ -133,9 +136,9 @@ "Are you sure you want to delete the selected address book?" = "Sei sicuro di voler cancellare la rubrica selezionata?"; "You cannot remove nor unsubscribe from a public addressbook." -= "You cannot remove nor unsubscribe from a public addressbook."; += "Non puoi rimuovere una rubrica pubblica."; "You cannot remove nor unsubscribe from your personal addressbook." -= "You cannot remove nor unsubscribe from your personal addressbook."; += "Non puoi rimuovere la tua rubrica personale."; "Are you sure you want to delete the selected contacts?" = "Sei sicuro di voler eliminare i contatti selezionati?"; diff --git a/UI/MailPartViewers/German.lproj/Localizable.strings b/UI/MailPartViewers/German.lproj/Localizable.strings index a9fb6b07d..5ad3a0969 100644 --- a/UI/MailPartViewers/German.lproj/Localizable.strings +++ b/UI/MailPartViewers/German.lproj/Localizable.strings @@ -1,12 +1,12 @@ ACCEPTED = "akzeptiert"; COMPLETED = "abgeschlossen"; DECLINED = "zurückgewiesen"; -DELEGATED = "weitergeleited"; +DELEGATED = "weitergeleitet"; IN-PROCESS = "in Bearbeitung"; NEEDS-ACTION = "Reaktion erwarted"; TENTATIVE = "vorläufig"; organized_by_you = "von Ihnen organisiert"; -you_are_an_attendee = "sind sind ein Teilnehmer"; +you_are_an_attendee = "Sie sind ein Teilnehmer"; add_info_text = "iMIP 'ADD' Anfragen werden von SOGo noch nicht unterstützt."; publish_info_text = "Der Sender informiert Sie über den angefügten Termin."; cancel_info_text = "Ihre Einladung zu dem Termin wurde abgesagt."; @@ -16,7 +16,7 @@ Appointment = "Termin"; Organizer = "Organisator"; Time = "Zeit"; Attendees = "Teilnehmer"; -request_info = "lädt sie ein an einem Treffen teilzunehmen."; +request_info = "lädt sie ein, an einem Treffen teilzunehmen."; "Add to calendar" = "Zum Kalender hinzufügen"; "Delete from calendar" = "Aus Kalender entfernen"; "Update status" = "Status aktualisieren"; diff --git a/UI/MailPartViewers/Italian.lproj/Localizable.strings b/UI/MailPartViewers/Italian.lproj/Localizable.strings index a1051d4cc..a5e46bdb4 100644 --- a/UI/MailPartViewers/Italian.lproj/Localizable.strings +++ b/UI/MailPartViewers/Italian.lproj/Localizable.strings @@ -7,7 +7,7 @@ NEEDS-ACTION = "richiede un'azione"; TENTATIVE = "tentativo"; organized_by_you = "organizzata da te"; you_are_an_attendee = "sei uno degli invitati"; -add_info_text = "Le richieste iMIP 'ADD' non sono ancora supportate da SOGo."; +add_info_text = "Le richieste IMIP 'ADD' non sono ancora supportate da SOGo."; publish_info_text = "Il mittente ti invia in allegato informazioni sull'evento."; cancel_info_text = "Il tuo invito o l'intero evento sono stati cancellati."; request_info_no_attendee = "sta proponento un incontro agli invitati. Ricevi questa email come notifica, non sei incluso come partecipante."; diff --git a/UI/MailerUI/Italian.lproj/Localizable.strings b/UI/MailerUI/Italian.lproj/Localizable.strings index 2a700fb12..efb9d7922 100644 --- a/UI/MailerUI/Italian.lproj/Localizable.strings +++ b/UI/MailerUI/Italian.lproj/Localizable.strings @@ -4,7 +4,7 @@ "Create" = "Crea"; "Empty Trash" = "Svuota cestino"; "Delete" = "Cancella"; -"Expunge" = "Expunge"; +"Expunge" = "Pulisci"; "Forward" = "Inoltra"; "Get Mail" = "Scarica posta"; "Junk" = "Indesiderato"; @@ -13,15 +13,15 @@ "Print" = "Stampa"; "Stop" = "Stop"; "Write" = "Scrivi"; -"Attachment" = "Attachment"; -"Unread" = "Unread"; +"Attachment" = "Allegato"; +"Unread" = "Non letta"; "Flagged" = "Flagged"; "Send" = "Invia"; "Contacts" = "Contatti"; "Attach" = "Allegato"; "Save" = "Salva"; -"Priority" = "Priority"; +"Priority" = "Priorità"; /* Tooltips */ @@ -74,7 +74,7 @@ "Add subfolders to this folder" = "Aggiungi sottocartelle a questa cartella"; "Remove this folder" = "Rimuovi questa cartella"; "Erase mails from this folder" = "Elimina emails da questa cartella"; -"Expunge this folder" = "Expugne per questa cartella"; +"Expunge this folder" = "Pulisci questa cartella"; "Modify the acl of this folder" = "Modifica i permessi per questa cartella"; "Update" = "Aggiorna"; @@ -104,15 +104,15 @@ "Anais" = "Anais"; "Edit Draft..." = "Modifica bozza..."; -"Load Images" = "Load Images"; +"Load Images" = "Carica Immagini"; -"highest" = "Highest"; -"high" = "High"; -"normal" = "Normal"; -"low" = "Low"; -"lowest" = "Lowest"; +"highest" = "Molto alta"; +"high" = "Alta"; +"normal" = "Normale"; +"low" = "Bassa"; +"lowest" = "Molto bassa"; -"This mail is being sent from an unsecure network!" = "Questa email è stata spedita da un network contrassegnato come non sicuro!"; +"This mail is being sent from an unsecure network!" = "Questa email è stata spedita da una rete contrassegnata come non sicuro!"; /* Popup "show" */ @@ -205,9 +205,9 @@ "View Message Source" = "Visualizza sorgente"; "Print..." = "Stampa..."; "Delete Message" = "Cancella messaggio"; -"Delete Selected Messages" = "Delete Selected Messages"; +"Delete Selected Messages" = "Cancella i messaggi selezionati"; -"This Folder" = "This Folder"; +"This Folder" = "Questa cartella"; /* Label popup menu */ "None" = "Nessuno"; @@ -230,7 +230,7 @@ /* Folder operations */ "Name :" = "Nome :"; "Enter the new name of your folder :" - = "Inserisci il nuovo nome della tua cartella :"; + = "Inserisci il nuovo nome della cartella :"; "Do you really want to move this folder into the trash ?" = "Sei sicuro di voler spostare la cartella nel cestino ?"; "Operation failed" = "Operazione non riuscita"; @@ -243,15 +243,15 @@ "Please select only one message to print." = "Per favore seleziona un solo messaggio da stampare."; "The folder with name \"%{0}\" could not be created." -= "The folder with name \"%{0}\" could not be created."; += "La cartella con nome \"%{0}\" non può essere creata."; "This folder could not be renamed to \"%{0}\"." -= "This folder could not be renamed to \"%{0}\"."; += "Questa cartella non puo essere rinominata in \"%{0}\"."; "The folder could not be deleted." -= "The folder could not be deleted."; += "Questa cartella non può essere eliminata."; "The trash could not be emptied." -= "The trash could not be emptied."; += "Il cestino non puo essere svuotato."; "The folder functionality could not be changed." -= "The folder functionality could not be changed."; += "La funzionalita della cartella non puo essere cambiata."; "You need to choose a non-virtual folder!" = "Devi selezionare una cartella fisica, non virtuale!"; diff --git a/UI/MainUI/Italian.lproj/Locale b/UI/MainUI/Italian.lproj/Locale index 3ac61a381..973294b2a 100644 --- a/UI/MainUI/Italian.lproj/Locale +++ b/UI/MainUI/Italian.lproj/Locale @@ -23,12 +23,12 @@ NSShortDateFormatString = "%d/%m/%y"; NSShortMonthNameArray = (Gen, Feb, Mar, Apr, Mag, Giu, Lug, Ago, Set, Ott, Nov, Dic); NSShortTimeDateFormatString = "%d/%m/%y %H:%M"; - NSShortWeekDayNameArray = (Lun, Mar, Mer, Gio, Ven, Sab, Dom); + NSShortWeekDayNameArray = (Dom, Lun, Mar, Mer, Gio, Ven, Sab); NSThisDayDesignations = (oggi, ora); NSThousandsSeparator = ","; NSTimeDateFormatString = "%A, %e %B, %Y %H:%M:%S %Z"; NSTimeFormatString = "%H:%M:%S"; - NSWeekDayNameArray = (Lunedi, Martedi, Mercoledi, Giovedi, Venerdi, Sabato, Domenica); + NSWeekDayNameArray = (Domenica, Lunedi, Martedi, Mercoledi, Giovedi, Venerdi, Sabato); NSYearMonthWeekDesignations = (anno, mese, settimana); NSPositiveCurrencyFormatString = "⬠9,999.00"; NSNegativeCurrencyFormatString = "-⬠9,999.00"; diff --git a/UI/MainUI/Italian.lproj/Localizable.strings b/UI/MainUI/Italian.lproj/Localizable.strings index 409d77d5f..d9c3e8d3b 100644 --- a/UI/MainUI/Italian.lproj/Localizable.strings +++ b/UI/MainUI/Italian.lproj/Localizable.strings @@ -14,8 +14,8 @@ "alternativeBrowserSafari" = "Alternativamente, puoi utilizzare Safari."; "Download" = "Scarica"; -"Language:" = "Language:"; -"choose" = "Choose ..."; +"Language:" = "Lingua:"; +"choose" = "Scegli..."; "Dutch" = "Dutch"; "English" = "Inglese"; "French" = "Francese"; diff --git a/UI/PreferencesUI/Italian.lproj/Localizable.strings b/UI/PreferencesUI/Italian.lproj/Localizable.strings index e4e1d79b5..12de9ffae 100644 --- a/UI/PreferencesUI/Italian.lproj/Localizable.strings +++ b/UI/PreferencesUI/Italian.lproj/Localizable.strings @@ -83,14 +83,14 @@ "Default identity:" = "Identità principale:"; "Manage identities..." = "Gestisci identità..."; "Signature" = "Firma"; -"replyplacement_above" = "replyplacement_above"; -"replyplacement_below" = "replyplacement_below"; -"And place my signature" = "And place my signature"; -"signatureplacement_above" = "signatureplacement_above"; -"signatureplacement_below" = "signatureplacement_below"; +"replyplacement_above" = "Inizia la risposta sopra il testo a cui si risponde"; +"replyplacement_below" = "Inizia la risposta sotto il testo a cui si risponde"; +"And place my signature" = "Metti la firma"; +"signatureplacement_above" = "sopra il testo a cui si risponde"; +"signatureplacement_below" = "sotto il testo a cui si risponde"; /* Additional Parameters */ -"Additional Parameters" = "Additional Parameters"; +"Additional Parameters" = "Parametri addizionali"; /* password */ "New password:" = "Nuova password:"; diff --git a/UI/Scheduler/German.lproj/Localizable.strings b/UI/Scheduler/German.lproj/Localizable.strings index 2317b6496..2760fad62 100644 --- a/UI/Scheduler/German.lproj/Localizable.strings +++ b/UI/Scheduler/German.lproj/Localizable.strings @@ -111,7 +111,7 @@ /* acls */ -"Default Roles" = "Standard-Rollen"; +"Default Roles" = "Standardrechte"; "User rights for:" = "Benutzerrechte für:"; "label_Public" = "Öffentlich"; @@ -131,9 +131,9 @@ "None" = "Keine"; "This person can create objects in my calendar." -= "Diese Person kann Termine in meinem Kalender hinzufügen."; += "Diese Person kann Objekte in meinem Kalender hinzufügen."; "This person can erase objects from my calendar." -= "Diese Person kann Termine in meinem Kalender löschen."; += "Diese Person kann Objekte in meinem Kalender löschen."; /* Button Titles */ @@ -397,7 +397,7 @@ /* transparency */ -"Show Time as Free" = "Zeige Zeit als Frei"; +"Show Time as Free" = "Zeige Zeit als Verfügbar"; /* validation errors */ @@ -439,7 +439,7 @@ validate_endbeforestart = "Ihr Beginn ist nach dem Ende"; "taskDeleteConfirmation" = "Wollen Sie diese Aufgabe wirklich dauerhaft löschen?"; "Are you sure you want to delete the calendar \"%{0}\"?" -= "Wollen Sie diesen Kalender wirklich dauerhaft löschen \"%{0}\"?"; += "Wollen Sie diesen Kalender wirklich löschen \"%{0}\"?"; /* Legend */ "Required participant" = "notwendiger Teilnehmer"; @@ -458,8 +458,8 @@ validate_endbeforestart = "Ihr Beginn ist nach dem Ende"; /* FreeBusy panel buttons */ "Suggest time slot:" = "Termin vorschlagen:"; -"Previous slot" = "Vorherige"; -"Next slot" = "Nächste"; +"Previous slot" = "Vorheriger"; +"Next slot" = "Nächster"; "Previous hour" = "Vorherige Stunde"; "Next hour" = "Nächste Stunde"; diff --git a/UI/Scheduler/Italian.lproj/Localizable.strings b/UI/Scheduler/Italian.lproj/Localizable.strings index d61c571c2..eb88730d2 100644 --- a/UI/Scheduler/Italian.lproj/Localizable.strings +++ b/UI/Scheduler/Italian.lproj/Localizable.strings @@ -24,6 +24,7 @@ "Thursday" = "Giovedi"; "Friday" = "Venerdi"; "Saturday" = "Sabato"; +"DayOfTheMonth" = "Giorno del mese"; "Sun" = "Dom"; "Mon" = "Lun"; @@ -95,7 +96,7 @@ "Sharing..." = "Condivisione"; "Export Calendar..." = "Esporta calendario..."; "Publish Calendar..." = "Pubblica calendario..."; -"Reload Remote Calendars" = "Aggiorna calendari Remoti"; +"Reload Remote Calendars" = "Aggiorna calendari remoti"; "Properties" = "Proprietà"; "Compose E-Mail to All Attendees" = "Invia Email a tutti gli invitati"; @@ -196,7 +197,7 @@ "Duration" = "Durata"; "Attendees:" = "Partecipanti:"; "Resources" = "Risorse"; -"Organizer:" = "Organizzatore:"; +"Organizer:" = "Proprietario:"; "Description:" = "Descrizione:"; "Document:" = "Documento:"; "Category:" = "Categoria:"; @@ -256,7 +257,10 @@ "All day Event" = "Tutta la giornata"; "check for conflicts" = "Controlla conflitti"; -"Browse URL" = "Cerca URL"; +"Browse URL" = "Mostra URL"; + +"newAttendee" = "Nuovo partecipante"; + /* calendar modes */ @@ -396,7 +400,7 @@ /* transparency */ -"Show Time as Free" = "Show Time as Free"; +"Show Time as Free" = "Mostra comunque come libero"; /* validation errors */ @@ -443,7 +447,7 @@ validate_endbeforestart = "La data finale specificata è precedente alla data /* Legend */ "Required participant" = "Richiede partecipanti"; "Optional participant" = "Partecipanti opzionali"; -"Chair" = "Chair"; +"Chair" = "Sedia"; "Needs action" = "Richiede un'azione"; "Accepted" = "Accettato"; @@ -491,4 +495,4 @@ vtodo_class2 = "(Attività confidenziale)"; /* Properties dialog */ "Name:" = "Nome:"; "Color:" = "Colore:"; -"Tag:" = "Tag:"; +"Tag:" = "Etichetta:";