Compare commits

...
22 Commits
Author SHA1 Message Date
Hivert Quentin b69ef6d7a5 chore(release): 5.12.3 2025-07-12 09:44:17 +02:00
Hivert Quentin 3ab86776e2 fix(calendar): fix recurrent event last date
Fix a bug introduces by #8766b7c
2025-07-08 15:26:09 +02:00
Hivert Quentin 7fa0daea43 chore(js/css): update generated files 2025-07-08 01:00:38 -04:00
Hivert Quentin 55dbae6bee fix(view): automatically refresh view only if a number is set. 2025-07-07 15:39:59 +02:00
Hivert Quentin d48befd151 chore(js/css): update generated files 2025-07-04 01:00:36 -04:00
Hivert Quentin f5f8f112cd chore(language): Add Thai language 2025-07-03 16:59:56 +02:00
Hivert Quentin 08bc6aff3f chore(language): Add Korean language 2025-07-03 09:35:50 +02:00
Hivert Quentin 8290cf2859 chore(doc): add doc por api 2025-06-25 14:16:17 +02:00
Hivert Quentin 8f03432a55 chore(release): 5.12.2 2025-06-25 09:34:32 +02:00
Hivert Quentin 9649ae345f i18n(pt): Update Portuguese translations 2025-06-25 08:52:35 +02:00
Hivert Quentin e9c03d3cf7 i18n(tr_TR): Update TurkishTurkey translations 2025-06-25 08:52:35 +02:00
Hivert Quentin 031e117cba i18n(nl): Update Dutch translations 2025-06-25 08:52:34 +02:00
Hivert Quentin dabad1d0cf fix(api): add handler for internal error 2025-06-24 10:20:12 +02:00
Hivert Quentin c1b6388260 chore(packaging): fix rhel packaging 2025-06-24 09:30:28 +02:00
Hivert Quentin bc6b849d66 chore(js/css): update generated files 2025-06-24 01:00:36 -04:00
Hivert Quentin 51f1521dba feat(api): add endpoint for caldav/cardav url 2025-06-23 17:14:39 +02:00
Hivert Quentin 516606baff fix(session): allow password/token to be longer than userkey 2025-06-23 09:27:51 +02:00
Hivert Quentin a782424a30 feat(openid): swicth to libcurl for http request
It was using an internal library before and there were too much errors due to incomplete http's protocol implementation
2025-06-23 09:24:02 +02:00
Hivert Quentin f53d7b73db fix(sieve): add requirements for notify when doing a filter 2025-06-19 09:40:58 +02:00
Hivert Quentin 8766b7c6b3 fix(calendar): properly evalute last occurance freebusy 2025-06-17 11:31:00 +02:00
Hivert Quentin 8a907737de fix(view): don't hide the option mailcomposer in small screen 2025-06-16 11:14:08 +02:00
Hivert Quentin 1a6f2825b6 chore(foc): put a link to the community version 2025-06-11 13:52:36 +02:00
205 changed files with 8066 additions and 257 deletions

No files matched your search

+1
View File
@@ -10,6 +10,7 @@
*/obj/
.scss-lint-config.yml_
ActiveSync/ActiveSync.SOGo
API/API.SOGo
Documentation/*.docbook
Documentation/*.pdf
Documentation/*.html
+1 -1
View File
@@ -1,6 +1,6 @@
[main]
host = https://www.transifex.com
lang_map = fr: French, pt_BR: BrazilianPortuguese, ru: Russian, sk: Slovak, es_AR: SpanishArgentina, fi: Finnish, id_ID: Indonesian, lt: Lithuanian, tr_TR: TurkishTurkey, zh_TW: ChineseTaiwan, ar: Arabic, cs: Czech, nn_NO: NorwegianNynorsk, sl_SI: Slovenian, uk: Ukrainian, zh_CN: ChineseChina, sv: Swedish, bg_BG: Bulgarian, cy: Welsh, is: Icelandic, sr: Serbian, lv: Latvian, pl: Polish, ro_RO: Romanian, bs_BA: Bosnian,ca: Catalan, he: Hebrew, kk: Kazakh, pt: Portuguese, es_ES: SpanishSpain, eu: Basque, hu: Hungarian, ja: Japanese, mk_MK: Macedonian, nb_NO: NorwegianBokmal, nl: Dutch, sr@latin: SerbianLatin, da_DK: Danish, de: German, hr_HR: Croatian, it: Italian, sr_ME@latin: Montenegrin, gl_ES: Galician
lang_map = fr: French, pt_BR: BrazilianPortuguese, ru: Russian, sk: Slovak, es_AR: SpanishArgentina, fi: Finnish, id_ID: Indonesian, lt: Lithuanian, tr_TR: TurkishTurkey, zh_TW: ChineseTaiwan, ar: Arabic, cs: Czech, nn_NO: NorwegianNynorsk, sl_SI: Slovenian, uk: Ukrainian, zh_CN: ChineseChina, sv: Swedish, bg_BG: Bulgarian, cy: Welsh, is: Icelandic, sr: Serbian, lv: Latvian, pl: Polish, ro_RO: Romanian, bs_BA: Bosnian,ca: Catalan, he: Hebrew, kk: Kazakh, pt: Portuguese, es_ES: SpanishSpain, eu: Basque, hu: Hungarian, ja: Japanese, mk_MK: Macedonian, nb_NO: NorwegianBokmal, nl: Dutch, sr@latin: SerbianLatin, da_DK: Danish, de: German, hr_HR: Croatian, it: Italian, sr_ME@latin: Montenegrin, gl_ES: Galician, ko: Korean, th: Thai
[o:alinto:p:sogo:r:soobjects-appointments]
source_file = SoObjects/Appointments/English.lproj/Localizable.strings
+28
View File
@@ -0,0 +1,28 @@
# GNUstep makefile
include common.make
BUNDLE_NAME = API
API_PRINCIPAL_CLASS = SOGoAPIProduct
API_OBJC_FILES = \
SOGoAPIProduct.m \
SOGoAPI.m \
SOGoAPIVersion.m \
SOGoAPIUserFolder.m \
SOGoAPIDispatcher.m
API_RESOURCE_FILES += \
product.plist
API_LANGUAGES = $(SOGO_LANGUAGES)
API_LOCALIZED_RESOURCE_FILES = Localizable.strings
ADDITIONAL_INCLUDE_DIRS += -I../SOPE/ -I../SoObjects/
-include GNUmakefile.preamble
include $(GNUSTEP_MAKEFILES)/bundle.make
-include GNUmakefile.postamble
+16
View File
@@ -0,0 +1,16 @@
# compile settings
ADDITIONAL_CPPFLAGS += \
-DSOGO_MAJOR_VERSION=$(MAJOR_VERSION) \
-DSOGO_MINOR_VERSION=$(MINOR_VERSION) \
-DSOGO_PATCH_VERSION=$(SUBMINOR_VERSION) \
-DSOGO_LIBDIR="@\"$(SOGO_LIBDIR)\""
ADDITIONAL_INCLUDE_DIRS += \
-D_GNU_SOURCE -I../SOPE/ -I../SoObjects/
ADDITIONAL_LIB_DIRS += \
-L../SoObjects/SOGo/SOGo.framework/sogo -lSOGo \
-L../SOPE/GDLContentStore/$(GNUSTEP_OBJ_DIR)/ -lGDLContentStore \
-L../SOPE/NGCards/$(GNUSTEP_OBJ_DIR)/ -lNGCards \
-lEOControl -lNGStreams -lNGMime -lNGExtensions -lNGObjWeb -lWEExtensions
+35
View File
@@ -0,0 +1,35 @@
/*
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of SOPE.
SOPE 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.
SOPE 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.
You should have received a copy of the GNU Lesser General Public
License along with SOPE; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#import <Foundation/Foundation.h>
#import <Foundation/NSObject.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSArray.h>
@class WOContext;
@interface SOGoAPI : NSObject
- (NSArray *) methodAllowed;
- (BOOL) needAuth;
- (NSArray *) paramNeeded;
- (NSDictionary *) action: (WOContext*) ctx withParam: (NSDictionary *) param;
@end
+52
View File
@@ -0,0 +1,52 @@
/*
Copyright (C) todo...
*/
#import <SOGoAPI.h>
@implementation SOGoAPI
- (id) init
{
[super init];
return self;
}
- (void) dealloc
{
[super dealloc];
}
- (NSArray *) methodAllowed
{
NSArray *result;
result = [NSArray arrayWithObjects:@"GET",nil];
return result;
}
- (BOOL) needAuth
{
return YES;
}
- (NSArray *) paramNeeded
{
return nil;
}
- (NSDictionary *) action: (WOContext*) ctx withParam: (NSDictionary *) param
{
NSDictionary* result;
result = [[NSDictionary alloc] initWithObjectsAndKeys:
@"API not defined", @"error",
nil];
[result autorelease];
return result;
}
@end /* SOGoAPI */
View File
Whitespace-only changes.
+54
View File
@@ -0,0 +1,54 @@
/*
Copyright (c) 2014-2015, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <Foundation/NSObject.h>
#import <SOGo/WORequest+SOGo.h>
#import <SOGo/WOResponse+SOGo.h>
@class NSCalendarDate;
@class NSException;
@class NSMutableDictionary;
@class NSURL;
@class NSNumber;
static volatile BOOL apiShouldTerminate = NO;
@interface SOGoAPIDispatcher : NSObject
{
id context;
BOOL debugOn;
}
- (NSException *) dispatchRequest: (WORequest*) theRequest
inResponse: (WOResponse*) theResponse
context: (id) theContext;
@end
+399
View File
@@ -0,0 +1,399 @@
/*
Copyright (c) 2014, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Inverse inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "SOGoAPIDispatcher.h"
#import <Foundation/NSAutoreleasePool.h>
#import <NGObjWeb/NSException+HTTP.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <NGObjWeb/WOCoreApplication.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGExtensions/NSString+misc.h>
#import <NGExtensions/NSString+Encoding.h>
#import <SOGo/SOGoSystemDefaults.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserManager.h>
#import <SOGo/NSString+Utilities.h>
#import <SOGo/WORequest+SOGo.h>
#import <SOGo/WOResponse+SOGo.h>
#import <SOGo/NSArray+Utilities.h>
#import <SOGo/NSString+Utilities.h>
#import <SOGo/SOGoOpenIdSession.h>
void handle_api_terminate(int signum)
{
NSLog(@"Forcing termination of API loop.");
apiShouldTerminate = YES;
[[WOCoreApplication application] terminateAfterTimeInterval: 1];
}
@implementation SOGoAPIDispatcher
- (id) init
{
[super init];
debugOn = [[SOGoSystemDefaults sharedSystemDefaults] apiDebugEnabled];
apiShouldTerminate = NO;
signal(SIGTERM, handle_api_terminate);
return self;
}
- (void) dealloc
{
[super dealloc];
}
- (void) _sendAPIErrorResponse: (WOResponse* ) response
withMessage: (NSString *) message
withStatus: (unsigned int) status
{
NSDictionary *msg;
msg = [[NSDictionary alloc] initWithObjectsAndKeys:
message, @"error",
nil];
[response setStatus: status];
[response setContent: [msg jsonRepresentation]];
}
- (NSString *) _getActionFromUri: (NSString *) _uri
{
/*
_uri always start with /SOGo/SOGoAPI
full _uri example /SOGo/SOGoAPI/Action/subaction1?param1&param2
*/
NSString *uriWithoutParams, *action, *prefix;
NSArray *uriSplits;
prefix = @"/SOGo/SOGoAPI";
action = @"";
uriWithoutParams = [_uri urlWithoutParameters];
if(![uriWithoutParams hasPrefix: prefix])
{
[self errorWithFormat: @"Uri for API request does not start with /SOGo/SOGoAPI: %@", uriWithoutParams];
return nil;
}
else
{
uriWithoutParams = [uriWithoutParams substringFromIndex:[prefix length]];
}
//remove first and last '/'' if needed
if([uriWithoutParams hasPrefix: @"/"])
{
uriWithoutParams = [uriWithoutParams substringFromIndex:1];
}
if([uriWithoutParams hasSuffix: @"/"])
{
uriWithoutParams = [uriWithoutParams substringToIndex:([uriWithoutParams length] -1)];
}
if([uriWithoutParams length] == 0)
{
[self warnWithFormat: @"Uri for API request has no action, make Version instead: %@", uriWithoutParams];
return @"SOGoAPIVersion";
}
else
{
uriSplits = [uriWithoutParams componentsSeparatedByString: @"/"];
action = [@"SOGoAPI" stringByAppendingString: [uriSplits objectAtIndex: 0]];
if(debugOn)
[self logWithFormat: @"API request, action made is %@", action];
}
return action;
}
- (NSDictionary *) _authBasicCheck: (NSString *) auth
{
NSDictionary *user;
NSRange rng;
NSString *decodeCred, *domain, *login, *pwd;
SOGoUserManager *lm;
SOGoPasswordPolicyError perr;
int expire, grace;
BOOL rc;
user = nil;
decodeCred = [[auth substringFromIndex:5] stringByTrimmingLeadWhiteSpaces];
decodeCred = [decodeCred stringByDecodingBase64];
rng = [decodeCred rangeOfString:@":"];
login = [decodeCred substringToIndex:rng.location];
pwd = [decodeCred substringFromIndex:(rng.location + rng.length)];
domain = nil;
perr = PolicyNoError;
rc = ([[SOGoUserManager sharedUserManager]
checkLogin: [login stringByReplacingString: @"%40"
withString: @"@"]
password: pwd
domain: &domain
perr: &perr
expire: &expire
grace: &grace
additionalInfo: nil]
&& perr == PolicyNoError);
if(rc)
{
//Fecth user info
lm = [SOGoUserManager sharedUserManager];
user = [lm contactInfosForUserWithUIDorEmail: login];
}
else
user = nil;
return user;
}
- (NSDictionary *) _authOpenId: (NSString *) auth withDomain: (NSString *) domain
{
NSDictionary *user;
NSString *token, *login;
SOGoOpenIdSession *openIdSession;
SOGoUserManager *lm;
user = nil;
token = [[auth substringFromIndex:6] stringByTrimmingLeadWhiteSpaces];
openIdSession = [SOGoOpenIdSession OpenIdSession: domain];
if(![openIdSession sessionIsOk])
{
[self errorWithFormat: @"API - OpenId server not found or has unexpected behavior, contact your admin."];
return nil;
}
[openIdSession setAccessToken: token];
login = [openIdSession login: @""];
if(login && ![login isEqualToString: @"anonymous"])
{
//Fecth user info
lm = [SOGoUserManager sharedUserManager];
user = [lm contactInfosForUserWithUIDorEmail: login];
}
else
user = nil;
return user;
}
- (NSException *) dispatchRequest: (WORequest*) theRequest
inResponse: (WOResponse*) theResponse
context: (id) theContext
{
NSAutoreleasePool *pool;
id activeUser;
NSString *method, *action, *error;
NSDictionary *form;
NSArray *paramNeeded;
NSMutableDictionary *paramInjected, *ret;
NSBundle *bundle;
id classAction;
Class clazz;
pool = [[NSAutoreleasePool alloc] init];
ASSIGN(context, theContext);
//Get the api action, check it
action = [self _getActionFromUri: [theRequest uri]];
if(!action)
{
error = [NSString stringWithFormat: @"No actions found for request to API: %@", [theRequest uri]];
[self errorWithFormat: error];
[self _sendAPIErrorResponse: theResponse withMessage: error withStatus: 400];
RELEASE(context);
RELEASE(pool);
return nil;
}
//Get the class for this action, check it
bundle = [NSBundle bundleForClass: NSClassFromString(@"SOGoAPIProduct")];
clazz = [bundle classNamed: action];
if(!clazz)
{
error = [NSString stringWithFormat: @"No backend API found for action: %@", action];
[self errorWithFormat: error];
[self _sendAPIErrorResponse: theResponse withMessage: error withStatus: 400];
RELEASE(context);
RELEASE(pool);
return nil;
}
//try to instantiate the class
NS_DURING
{
classAction = [[clazz alloc] init];
}
NS_HANDLER
{
error = [NSString stringWithFormat: @"Can't alloc and init class: %@", classAction];
[self errorWithFormat: error];
[self _sendAPIErrorResponse: theResponse withMessage: error withStatus: 500];
RELEASE(context);
RELEASE(pool);
return nil;
}
NS_ENDHANDLER;
//Check method
method = [theRequest method];
if(![[classAction methodAllowed] containsObject: method])
{
error = [NSString stringWithFormat: @"Method %@ not allowed for action %@", method, action];
[self errorWithFormat: error];
[self _sendAPIErrorResponse: theResponse withMessage: error withStatus: 400];
RELEASE(context);
RELEASE(pool);
return nil;
}
paramInjected = [NSMutableDictionary dictionary];
//Check parameters
if((paramNeeded = [classAction paramNeeded]) && [paramNeeded count] >= 1)
{
NSDictionary* formAndQuery = [theRequest formValues];
for(NSString *param in paramNeeded)
{
id value;
if((value = [formAndQuery objectForKey: param]))
{
NSString* trueValue;
if ([value isKindOfClass: [NSArray class]])
trueValue = [value lastObject];
else
trueValue = value;
[paramInjected setObject: trueValue forKey: param];
}
else
{
error = [NSString stringWithFormat: @"Missing param %@ for action %@", param, action];
[self errorWithFormat: error];
[self _sendAPIErrorResponse: theResponse withMessage: error withStatus: 400];
RELEASE(context);
RELEASE(pool);
return nil;
}
}
}
if([classAction needAuth])
{
if(debugOn)
[self logWithFormat: @"Check auth for action %@", action];
//check auth
NSString *auth = [theRequest headerForKey: @"authorization"];
if(auth)
{
NSDictionary* user;
if([[auth lowercaseString] hasPrefix: @"basic"])
{
//basic auth
user = [self _authBasicCheck: auth];
}
else if([[auth lowercaseString] hasPrefix: @"bearer"])
{
//openid auth, we may need to know the user-domain to know which openid server to fetch
NSString *domain = [theRequest headerForKey: @"user-domain"];
user = [self _authOpenId: auth withDomain: domain];
}
else
{
error = [NSString stringWithFormat: @"Authorization method incorrect: %@ for action %@", auth, action];
[self errorWithFormat: error];
[self _sendAPIErrorResponse: theResponse withMessage: error withStatus: 401];
RELEASE(context);
RELEASE(pool);
return nil;
}
//add current user in paramInjected
if(user){
if(debugOn)
[self logWithFormat: @"User authenticated %@", user];
[paramInjected setObject: user forKey: @"user"];
}
else
{
error = [NSString stringWithFormat: @"User wrong login or not found for action %@", action];
[self errorWithFormat: error];
[self _sendAPIErrorResponse: theResponse withMessage: error withStatus: 401];
RELEASE(context);
RELEASE(pool);
return nil;
}
}
else
{
error = [NSString stringWithFormat: @"No authorization header found for action %@", action];
[self errorWithFormat: error];
[self _sendAPIErrorResponse: theResponse withMessage: error withStatus: 401];
RELEASE(context);
RELEASE(pool);
return nil;
}
}
//Execute action
NS_DURING
{
ret = [classAction action: context withParam: paramInjected];
}
NS_HANDLER
{
error = [NSString stringWithFormat: @"Internal error during: %@", action];
[self errorWithFormat: error];
[self _sendAPIErrorResponse: theResponse withMessage: error withStatus: 500];
RELEASE(context);
RELEASE(pool);
return nil;
}
NS_ENDHANDLER;
//Make the response
[theResponse setContent: [ret jsonRepresentation]];
RELEASE(context);
RELEASE(pool);
return nil;
}
@end
+11
View File
@@ -0,0 +1,11 @@
/*
Copyright (C) todo...
*/
#import <Foundation/NSObject.h>
@interface SOGoAPIProduct : NSObject
@end
@implementation SOGoAPIProduct
@end /* SOGoAPIProduct */
+33
View File
@@ -0,0 +1,33 @@
/*
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of SOPE.
SOPE 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.
SOPE 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.
You should have received a copy of the GNU Lesser General Public
License along with SOPE; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#import <Foundation/Foundation.h>
#import <Foundation/NSObject.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSArray.h>
#import <SOGoAPI.h>
@class WOContext;
@interface SOGoAPIUserFolder : SOGoAPI
- (NSArray *) methodAllowed;
- (NSDictionary *) action: (WOContext*) ctx withParam: (NSDictionary *) param;
@end
+110
View File
@@ -0,0 +1,110 @@
/*
Copyright (C) todo...
*/
#import <SOGoAPIUserFolder.h>
#import <GDLContentStore/GCSFolderManager.h>
#import <GDLContentStore/GCSFolder.h>
@implementation SOGoAPIUserFolder
- (id) init
{
[super init];
return self;
}
- (void) dealloc
{
[super dealloc];
}
/**
{
"calendar":[
{
"name":"DidyShared",
"url":"http://127.0.0.1/SOGo/dav/sogo-tests1@example.org/Calendar/12509-67F67D00-1-3105AF40"
},
{
"name":"LocalDidy",
"url":"http://127.0.0.1/SOGo/dav/sogo-tests1@example.org/Calendar/1BC38-67B60000-1-6E4B6880"
},
{
"name":"Personal Calendar",
"url":"http://127.0.0.1/SOGo/dav/sogo-tests1@example.org/Calendar/personal"
}
],
"username":"sogo-tests1@example.org",
"contact":[
{
"name":"Personal Address Book",
"url":"http://127.0.0.1/SOGo/dav/sogo-tests1@example.org/Contacts/personal"
}
]
}
**/
- (NSDictionary *) action: (WOContext*) ctx withParam: (NSDictionary *) param
{
NSDictionary* result;
NSArray *folders;
NSMutableArray *cardavLinks, *caldavLinks;
NSString *serverUrl, *basePath, *c_uid, *url;
GCSFolderManager *fm;
GCSFolder *folder;
int max, i;
//Should be a user
c_uid = [[[param objectForKey: @"user"] objectForKey: @"emails"] objectAtIndex: 0];
//fetch folders
fm = [GCSFolderManager defaultFolderManager];
basePath = [NSString stringWithFormat: @"/Users/%@", c_uid];
folders = [fm listSubFoldersAndNamesAtPath: basePath recursive: YES];
//Generate dav link
max = [folders count];
serverUrl = [[ctx serverURL] absoluteString];
cardavLinks = [NSMutableArray array];
caldavLinks = [NSMutableArray array];
serverUrl = [[ctx serverURL] absoluteString];
for (i = 0; i < max; i++)
{
NSMutableDictionary *folderRet;
folderRet = [NSMutableDictionary dictionary];
folder = [folders objectAtIndex: i];
url = [NSString stringWithFormat: @"%@/SOGo/dav/%@/%@", serverUrl, c_uid, [folder objectForKey: @"path"]];
[folderRet setObject: url forKey: @"url"];
[folderRet setObject: [folder objectForKey: @"name"] forKey: @"name"];
if([url rangeOfString:@"/Calendar/"].location == NSNotFound)
{
//Contacts
[cardavLinks addObject: folderRet];
}
else
{
//Calendar
[caldavLinks addObject: folderRet];
}
}
result = [[NSDictionary alloc] initWithObjectsAndKeys:
c_uid, @"username",
cardavLinks, @"contact",
caldavLinks, @"calendar",
nil];
[result autorelease];
return result;
}
@end /* SOGoAPIVersion */
+33
View File
@@ -0,0 +1,33 @@
/*
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of SOPE.
SOPE 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.
SOPE 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.
You should have received a copy of the GNU Lesser General Public
License along with SOPE; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#import <Foundation/Foundation.h>
#import <Foundation/NSObject.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSArray.h>
#import <SOGoAPI.h>
@class WOContext;
@interface SOGoAPIVersion : SOGoAPI
- (NSArray *) methodAllowed;
- (NSDictionary *) action: (WOContext*) ctx withParam: (NSDictionary *) param;
@end
+42
View File
@@ -0,0 +1,42 @@
/*
Copyright (C) todo...
*/
#import <SOGoAPIVersion.h>
@implementation SOGoAPIVersion
- (id) init
{
[super init];
return self;
}
- (void) dealloc
{
[super dealloc];
}
- (BOOL) needAuth
{
return NO;
}
- (NSDictionary *) action: (WOContext*) ctx withParam: (NSDictionary *) param
{
NSDictionary* result;
result = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithInt:SOGO_MAJOR_VERSION], @"major",
[NSNumber numberWithInt:SOGO_MINOR_VERSION], @"minor",
[NSNumber numberWithInt:SOGO_PATCH_VERSION], @"patch",
nil];
[result autorelease];
return result;
}
@end /* SOGoAPIVersion */
+34
View File
@@ -0,0 +1,34 @@
include ../config.make
include $(GNUSTEP_MAKEFILES)/common.make
include ../Version
NEEDS_GUI=no
BUNDLE_EXTENSION = .SOGo
BUNDLE_INSTALL_DIR = $(SOGO_LIBDIR)
WOBUNDLE_EXTENSION = $(BUNDLE_EXTENSION)
WOBUNDLE_INSTALL_DIR = $(BUNDLE_INSTALL_DIR)
# SYSTEM_LIB_DIR += -L/usr/local/lib -L/usr/lib
ADDITIONAL_INCLUDE_DIRS += \
-I.. \
-I../.. \
-I../../SOPE
ADDITIONAL_LIB_DIRS += \
-L../SoObjects/SOGo/SOGo.framework/Versions/Current/sogo \
-L../SoObjects/SOGo/$(GNUSTEP_OBJ_DIR)/ \
-L../SOPE/NGCards/$(GNUSTEP_OBJ_DIR)/ \
-L/usr/local/lib \
-Wl,-rpath,$(SOGO_SYSLIBDIR)/sogo
BUNDLE_LIBS += \
-lSOGo \
-lGDLContentStore \
-lGDLAccess \
-lNGObjWeb \
-lNGCards -lNGMime -lNGLdap \
-lNGStreams -lNGExtensions -lEOControl \
-lDOM -lSaxObjC -lSBJson
ADDITIONAL_BUNDLE_LIBS += $(BUNDLE_LIBS)
+31
View File
@@ -0,0 +1,31 @@
{
requires = ( MAIN, Appointments, Contacts, Mailer );
publicResources = ();
factories = {};
classes = {
SOGoAPI = {
protectedBy = "<public>";
defaultRoles = {
"View" = ( "Authenticated", "PublicUser" );
};
};
};
categories = {
SOGoAPI = {
slots = {
};
methods = {
Version = {
protectedBy = "View";
pageName = "SOGoAPI";
actionName = "sogoVersion";
};
};
};
};
}
+36
View File
@@ -2,6 +2,42 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [5.12.3](https://github.com/Alinto/sogo/compare/SOGo-5.12.2...SOGo-5.12.3) (2025-07-12)
### Bug Fixes
* **calendar:** fix recurrent event last date ([3ab8677](https://github.com/Alinto/sogo/commit/3ab86776e2ea826e043e3a0519097538853d82e3)), closes [#8766b7](https://bugs.sogo.nu/view.php?id=8766b7)
* **view:** automatically refresh view only if a number is set. ([55dbae6](https://github.com/Alinto/sogo/commit/55dbae6bee9bdd1aa00333320ba076617cbfb0fc))
## [5.12.2](https://github.com/Alinto/sogo/compare/SOGo-5.12.1...SOGo-5.12.2) (2025-06-25)
### Features
* **api:** add endpoint for caldav/cardav url ([51f1521](https://github.com/Alinto/sogo/commit/51f1521dba2d0ca8bdbadffadb16db26b975f668))
* **openid:** swicth to libcurl for http request ([a782424](https://github.com/Alinto/sogo/commit/a782424a30cfe8e9c6f2769a45bcdd3498679237))
### Bug Fixes
* **api:** add handler for internal error ([dabad1d](https://github.com/Alinto/sogo/commit/dabad1d0cf46263d78558d79d2af9fff528a9a89))
* **calendar:** properly evalute last occurance freebusy ([8766b7c](https://github.com/Alinto/sogo/commit/8766b7c6b32aedf37d7f8f350e461931b253a4fb))
* **openid:** add state in connection flow ([085fc4a](https://github.com/Alinto/sogo/commit/085fc4a9eb7d1e2a0f7b48baa1f09a8ba0d515e1))
* **openid:** allow expires_in param to be null ([9954c36](https://github.com/Alinto/sogo/commit/9954c3607bfda55424f5ac532a1075407235f345))
* **openid:** make end_session_endpoint optional ([c5fb348](https://github.com/Alinto/sogo/commit/c5fb3482e22f1bfc935213e8ed7208becd9bd1f4))
* **password:** put correct regex for special char ([e36d0d2](https://github.com/Alinto/sogo/commit/e36d0d219baed8c7d57af0069fadb8d1bf7df072))
* **session:** allow password/token to be longer than userkey ([516606b](https://github.com/Alinto/sogo/commit/516606baff5674c25da1e76f532ca2a9d7818ec0))
* **sieve:** add requirements for notify when doing a filter ([f53d7b7](https://github.com/Alinto/sogo/commit/f53d7b73db3d87a17a253bf98ee09a80052b3fd8))
* **view:** don't hide the option mailcomposer in small screen ([8a90773](https://github.com/Alinto/sogo/commit/8a907737de336f873047ecdc7d5c8ac07ae9e45b))
### Localization
* **nl:** Update Dutch translations ([031e117](https://github.com/Alinto/sogo/commit/031e117cbacf9d41caff43be19e639dee81b84dc))
* **pt:** Update Portuguese translations ([9649ae3](https://github.com/Alinto/sogo/commit/9649ae345f334d390860b0db70db8c3b621f513e))
* **tr_TR:** Update TurkishTurkey translations ([e9c03d3](https://github.com/Alinto/sogo/commit/e9c03d3cf7e668866ac757f72d87cdc4709c9d33))
## [5.12.1](https://github.com/Alinto/sogo/compare/SOGo-5.12.0...SOGo-5.12.1) (2025-04-30)
@@ -193,6 +193,9 @@ should apply to all supported operating systems.
Software Downloads
~~~~~~~~~~~~~~~~~~
**In order to access the community build, go to https://www.sogo.nu/download.html[SOGo website]
and select "Development (nightly builds)" at the bottom of the page.**
[NOTE]
In order to access the production builds, you need a proper support contract
from https://sogo.nu/support/index_new.html#support-plans[Alinto]. Continue
@@ -1564,6 +1567,8 @@ expected by pam_cas, otherwise it will fail to authenticate incoming
connection properly.
[[openid-section]]
Authenticating using OPENID
~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -4118,6 +4123,155 @@ sogo-tool user-preferences set defaults user1 Forward -f /path/filename -p cred
----
API REST
--------
Starting from 5.12.2, an API with two endpoints is available.
All response will be on json format. In case of errors, the message will be:
```json
{"error" : "message"}
```
with an explicit message
API server url
~~~~~~~~~~~~~~
_<scheme>_://_<domain>_/SOGo/SOGoAPI/_<action>_
• *scheme* : https or http
• *domain* : domain or ip:port of SOGo's server
• *action* : name of the action. No action does the Version action described below.
Authentication
~~~~~~~~~~~~~~
Somes actions needs to be authenticated. There is two ways to do so:
* *Basic auth*
Add a header *Auhtorization* with value:
'Basic <credentials>'
*credentials* is the sitrng '<uid>:<password>' base64 encoded.
* *OpenID*
**Only works if you configure sogo to use openid. See <<openid-section, the related section>>**
Add a header *Auhtorization* with value:
'Bearer <access_token>'
*acces_token* is from the https://connect2id.com/products/server/docs/api/token#url[openid protocol]. It has to be fetch with the scope `openid`.
Action - Version
~~~~~~~~~~~~~~~~
* *URL*: <scheme>://<domain>/SOGo/SOGoAPI/Version
* *Authentication needed*: NO
* *HTTP method allowed*: GET
* *Description*: Return the current version of sogo
* *Answer structure*:
```json
{
"major":5,
"patch":1,
"minor":12
}
```
Action - UserFolder
~~~~~~~~~~~~~~~~~~~
* *URL*: <scheme>://<domain>/SOGo/SOGoAPI/UserFolder
* *Authentication needed*: YES
* *HTTP method allowed*: GET
* *Description*: Return the caldav and cardav links of the authenticated user, plus their names.
* *Answer structure*:
```json
{
"calendar":[
{
"name":"DidyShared",
"url":"http://127.0.0.1/SOGo/dav/sogo-tests1@example.org/Calendar/12509-67F67D00-1-3105AF40"
},
{
"name":"LocalDidy",
"url":"http://127.0.0.1/SOGo/dav/sogo-tests1@example.org/Calendar/1BC38-67B60000-1-6E4B6880"
},
{
"name":"Personal Calendar",
"url":"http://127.0.0.1/SOGo/dav/sogo-tests1@example.org/Calendar/personal"
}
],
"username":"sogo-tests1@example.org",
"contact":[
{
"name":"Personal Address Book",
"url":"http://127.0.0.1/SOGo/dav/sogo-tests1@example.org/Contacts/personal"
}
]
}
```
* *Note*:
The Answer has 3 primary keys:
** *username*: uid of the user.
** *calendar*: array of calendar's folder info.
** *contact*: array of calendar's folder info.
A folder info is a dict with:
** *name*: Name of the folder.
** *url*: Dav link of the folder.
Errors and messages
~~~~~~~~~~~~~~~~~~~
Complete http response is `{“error:” : <message>}`.
*<action>* is the one used for the request: `<scheme>://<domain>/SOGo/SOGoAPI/<action>`
[%header,cols="1,3,3"]
|===
|Status |Message |Description
|400
|No backend API found for action: <action>
|The requested action doesn't exist
|500
|Can't alloc and init class: <classAction>
|The requested action exist but failed to be instantiated. <classAction> is the class's name
|400
|Method <method> not allowed for action <action>
|Http method not allowed. <methos> is the one used (GET, PUT, POST...)
|400
|Missing param <param> for action <action>
|Required param for action not found. <param> is the name of the missing parameter.
|401
|No authorization header found for <action>
|No Authorization header found
|401
|Authorization method incorrect: <auth> for action <action>
|Value of Authorization's header doesn't start with Basic or Bearer. <auth> is the full value.
|401
|User wrong login or not found for action <action>
|Fail to authenticate the user. Various causes possible: wrong login, wrong password, expired token...
|500
|Internal error during: <action>
|Internal error during the action
|===
To have more logs you can add `SOGoAPIDebugEnabled = YES;` to your sogo.conf.
Upgrading
---------
+1
View File
@@ -9,6 +9,7 @@ SUBPROJECTS = \
SoObjects \
Main \
UI \
API \
Tools \
Tests/Unit \
+8 -2
View File
@@ -417,7 +417,7 @@ static BOOL debugLeaks;
{
id obj;
WORequest *request;
BOOL isDAVRequest;
BOOL isDAVRequest, isAPIRequest;
SOGoSystemDefaults *sd;
/* put locale info into the context in case it's not there */
@@ -425,8 +425,14 @@ static BOOL debugLeaks;
sd = [SOGoSystemDefaults sharedSystemDefaults];
request = [_ctx request];
isAPIRequest = [[request requestHandlerKey] isEqualToString:@"SOGoAPI"];
isDAVRequest = [[request requestHandlerKey] isEqualToString:@"dav"];
if (isDAVRequest || [sd isWebAccessEnabled])
if(isAPIRequest && ![_key isEqualToString:@"SOGo"] && ![_key isEqualToString:@"SOGoAPI"])
{
//The request will be handle by the API Dispatcher
obj = nil;
}
else if (isDAVRequest || [sd isWebAccessEnabled])
{
if (isDAVRequest)
{
+1
View File
@@ -76,6 +76,7 @@
- (BOOL)folderExistsAtPath:(NSString *)_path;
- (NSArray *)listSubFoldersAtPath:(NSString *)_path recursive:(BOOL)_flag;
- (NSArray *)listSubFoldersAndNamesAtPath:(NSString *)_path recursive:(BOOL)_recursive;
- (NSDictionary *) recordAtPath: (NSString *) _path;
- (GCSFolder *)folderAtPath:(NSString *)_path;
+87
View File
@@ -598,6 +598,27 @@ static BOOL _singleStoreMode = NO;
return sql;
}
- (NSString *)generateSQLPathAndNameFetchForInternalNames:(NSArray *)_names
exactMatch:(BOOL)_beExact orDirectSubfolderMatch:(BOOL)_directSubs
{
/* fetches the 'path' subset for a given quick-names */
NSMutableString *sql;
NSString *ws;
ws = [self generateSQLWhereForInternalNames:_names
exactMatch:_beExact orDirectSubfolderMatch:_directSubs];
if ([ws length] == 0)
return nil;
sql = [NSMutableString stringWithCapacity:256];
[sql appendString:@"SELECT c_path, c_foldername FROM "];
[sql appendString:[self folderInfoTableName]];
[sql appendString:@" WHERE "];
[sql appendString:ws];
if (debugSQLGen) [self logWithFormat:@"PathFetch-SQL: %@", sql];
return sql;
}
/* handling folder names */
- (BOOL)_isStandardizedPath:(NSString *)_path {
@@ -806,6 +827,72 @@ static BOOL _singleStoreMode = NO;
return result;
}
- (NSArray *)listSubFoldersAndNamesAtPath:(NSString *)_path recursive:(BOOL)_recursive{
NSMutableArray *result;
NSString *fname;
NSArray *fnames, *records;
NSString *sql;
unsigned i, count;
if ((fnames = [self internalNamesFromPath:_path]) == nil) {
[self debugWithFormat:@"got no internal names for path: '%@'", _path];
return nil;
}
sql = [self generateSQLPathAndNameFetchForInternalNames:fnames
exactMatch:NO orDirectSubfolderMatch:(_recursive ? NO : YES)];
if ([sql length] == 0) {
[self debugWithFormat:@"got no SQL for names: %@", fnames];
return nil;
}
if ((records = [self performSQL:sql]) == nil) {
[self logWithFormat:@"ERROR(%s): executing SQL failed: '%@'",
__PRETTY_FUNCTION__, sql];
return nil;
}
if ((count = [records count]) == 0)
return emptyArray;
result = [NSMutableArray arrayWithCapacity:(count > 128 ? 128 : count)];
fname = [self internalNameFromPath:_path];
fname = [fname stringByAppendingString:@"/"]; /* add slash */
for (i = 0; i < count; i++) {
NSDictionary *record, *folderInfo;
NSString *sname, *spath, *foldername;
record = [records objectAtIndex:i];
sname = [record objectForKey:GCSPathRecordName];
if (![sname hasPrefix:fname]) /* does not match at all ... */
continue;
/* strip prefix and following slash */
sname = [sname substringFromIndex:[fname length]];
spath = [self pathPartFromInternalName:sname];
if (_recursive) {
if ([spath length] > 0){
foldername = [record objectForKey: @"c_foldername"];
folderInfo = [NSDictionary dictionaryWithObjectsAndKeys: spath, @"path", foldername, @"name", nil];
[result addObject:folderInfo];
}
}
else {
/* direct children only, so exclude everything with a slash */
if ([sname rangeOfString:@"/"].length == 0 && [spath length] > 0)
{
foldername = [record objectForKey: @"c_foldername"];
folderInfo = [NSDictionary dictionaryWithObjectsAndKeys: spath, @"path", foldername, @"name", nil];
[result addObject:folderInfo];
}
}
}
return result;
}
- (NSDictionary *) recordAtPath: (NSString *) _path
{
NSMutableString *sql;
+1 -1
View File
@@ -303,8 +303,8 @@ static NSString *openIdFolderURLString = nil;
newRecord = [NSDictionary dictionaryWithObjectsAndKeys: _user_session, @"c_user_session",
_old_session, @"c_old_session",
[NSNumber numberWithInt:now], @"c_session_started",
_refresh_token, @"c_refresh_token",
[NSNumber numberWithInt:nowExpire] , @"c_access_token_expires_in",
_refresh_token, @"c_refresh_token",
[NSNumber numberWithInt:nowRefreshExpire] , @"c_refresh_token_expires_in",
nil];
record = [self recordForSession: _user_session useOldSession: NO];
+17 -9
View File
@@ -55,7 +55,7 @@
- (NSArray *) recurrenceRangesWithinCalendarDateRange: (NGCalendarDateRange *) _r
{
NSMutableArray *ranges;
NSCalendarDate *firStart, *startDate, *endDate, *currentStartDate, *currentEndDate;
NSCalendarDate *firStart, *firEnd, *startDate, *endDate, *currentStartDate, *currentEndDate;
iCalByDayMask *dayMask;
long i, count, repeatCount;
unsigned interval;
@@ -63,6 +63,7 @@
//[self logWithFormat: @"Recurrence rule is %@", rrule];
firStart = [firstRange startDate];
firEnd = [firstRange endDate];
startDate = [_r startDate];
endDate = [_r endDate];
dayMask = nil;
@@ -84,34 +85,41 @@
// If rule is bound, check the bounds
if (![rrule isInfinite])
{
NSCalendarDate *until, *lastDate;
NSCalendarDate *until, *lastStartDate, *lastEndDate;
lastDate = nil;
lastStartDate = nil;
lastEndDate = nil;
until = [rrule untilDate];
if (until)
{
lastDate = until;
lastStartDate = until;
lastEndDate = until;
}
else
{
repeatCount = [rrule repeatCount];
if (dayMask == nil)
{
// If there's no day mask, we can compute the date of the last
// occurrence of the recurrent rule.
lastDate = [firStart dateByAddingYears: 0 months: 0
lastStartDate = [firStart dateByAddingYears: 0 months: 0
days: (interval
* (repeatCount - 1))];
lastEndDate = [firEnd dateByAddingYears: 0 months: 0
days: (interval
* (repeatCount - 1))];
}
}
if (lastDate != nil)
if (lastStartDate != nil && lastEndDate != nil)
{
if ([lastDate compare: startDate] == NSOrderedAscending)
if ([lastEndDate compare: startDate] == NSOrderedAscending)
// Range starts after last occurrence
return nil;
if ([lastDate compare: endDate] == NSOrderedAscending)
if ([lastStartDate compare: endDate] == NSOrderedAscending)
// Range ends after last occurence; adjust end date
endDate = lastDate;
endDate = lastStartDate;
}
}
+15 -9
View File
@@ -185,7 +185,7 @@ static inline unsigned iCalDoWForNSDoW (int dow)
// TODO: check whether this is OK for multiday-events!
NSMutableArray *ranges;
NSTimeZone *timeZone;
NSCalendarDate *eventStartDate, *rStart, *rEnd, *until, *referenceDate;
NSCalendarDate *eventStartDate, *eventEndDate, *rStart, *rEnd, *untilStart, *untilEnd, *referenceDate;
int eventDayOfMonth;
unsigned monthIdxInRange, numberOfMonthsInRange, interval, repeatCount;
int diff, count;
@@ -199,12 +199,14 @@ static inline unsigned iCalDoWForNSDoW (int dow)
iCalByDayMask *byDayMask;
eventStartDate = [firstRange startDate];
eventEndDate = [firstRange endDate];
eventDayOfMonth = [eventStartDate dayOfMonth];
timeZone = [eventStartDate timeZone];
rStart = [_r startDate];
rEnd = [_r endDate];
interval = [rrule repeatInterval];
until = nil;
untilStart = nil;
untilEnd = nil;
repeatCount = [rrule repeatCount];
byMonth = [rrule byMonth];
byMonthDay = [rrule byMonthDay];
@@ -218,24 +220,28 @@ static inline unsigned iCalDoWForNSDoW (int dow)
{
// When there's no BYxxx mask, we can find the date of the last
// occurrence.
until = [eventStartDate dateByAddingYears: 0
untilStart = [eventStartDate dateByAddingYears: 0
months: (interval * (repeatCount - 1))
days: 0];
untilEnd = [eventEndDate dateByAddingYears: 0
months: (interval * (repeatCount - 1))
days: 0];
}
else
{
until = [rrule untilDate];
untilStart = [rrule untilDate];
untilEnd = [rrule untilDate];
}
}
if (until != nil)
if (untilStart != nil && untilEnd != nil)
{
if ([until compare: rStart] == NSOrderedAscending)
if ([untilEnd compare: rStart] == NSOrderedAscending)
// Range starts after last occurrence
return nil;
if ([until compare: rEnd] == NSOrderedAscending)
if ([untilStart compare: rEnd] == NSOrderedAscending)
// Range ends after last occurence; adjust end date
rEnd = until;
rEnd = untilStart;
}
if (byMonth && [byMonth count] > 0)
@@ -441,7 +447,7 @@ static inline unsigned iCalDoWForNSDoW (int dow)
start = [cursor dateByAddingYears: 0 months: 0 days: (dom - 1)];
doCont = [self _addInstanceWithStartDate: start
limitDate: until
limitDate: untilStart
limitRange: _r
toArray: ranges];
//NSLog(@"*** MONTHLY [%i/%i] adding %@%@ (count = %i)", dom, numDaysInMonth, start, (doCont?@"":@" .. NOT!"), count);
+19 -9
View File
@@ -64,7 +64,7 @@
- (NSArray *) recurrenceRangesWithinCalendarDateRange: (NGCalendarDateRange *) _r
{
NSMutableArray *ranges;
NSCalendarDate *firStart, *startDate, *endDate, *currentStartDate, *currentEndDate;
NSCalendarDate *firStart, *firEnd, *startDate, *endDate, *currentStartDate, *currentEndDate;
long i, repeatCount, count;
unsigned interval;
iCalByDayMask *dayMask;
@@ -73,6 +73,7 @@
//[self logWithFormat: @"Recurrence rule is %@", rrule];
firStart = [firstRange startDate];
firEnd = [firstRange endDate];
startDate = [_r startDate];
endDate = [_r endDate];
dayMask = nil;
@@ -95,31 +96,40 @@
// If rule is bound, check the bounds
if (![rrule isInfinite])
{
NSCalendarDate *until, *lastDate;
NSCalendarDate *until, *lastStartDate, *lastEndDate;
lastDate = nil;
lastStartDate = nil;
lastEndDate = nil;
until = [rrule untilDate];
if (until)
lastDate = until;
{
lastStartDate = until;
lastEndDate = until;
}
else
{
repeatCount = [rrule repeatCount];
if (dayMask == nil)
{
// When there's no BYxxx mask, we can find the date of the last
// occurrence.
lastDate = [firStart dateByAddingYears: 0 months: 0
lastStartDate = [firStart dateByAddingYears: 0 months: 0
days: (interval
* (repeatCount - 1) * 7)];
lastEndDate = [firEnd dateByAddingYears: 0 months: 0
days: (interval
* (repeatCount - 1) * 7)];
}
}
if (lastDate != nil)
if (lastStartDate != nil && lastEndDate != nil)
{
if ([lastDate compare: startDate] == NSOrderedAscending)
if ([lastEndDate compare: startDate] == NSOrderedAscending)
// Range starts after last occurrence
return nil;
if ([lastDate compare: endDate] == NSOrderedAscending)
if ([lastStartDate compare: endDate] == NSOrderedAscending)
// Range ends after last occurence; adjust end date
endDate = [lastDate addTimeInterval: [firstRange duration]];
endDate = [lastStartDate addTimeInterval: [firstRange duration]];
}
}
+17 -9
View File
@@ -44,13 +44,14 @@
{
NSMutableArray *ranges;
NSArray *byMonth;
NSCalendarDate *firStart, *lastDate, *rStart, *rEnd, *until, *referenceDate, *rTemp;
NSCalendarDate *firStart, *firEnd, *lastStartDate, *lastEndDate, *rStart, *rEnd, *until, *referenceDate, *rTemp;
NSInteger *hoursOfOffset;
iCalMonthlyRecurrenceCalculator *monthlyCalc;
unsigned j, yearIdxInRange, numberOfYearsInRange, count, interval, monthDiff;
int diff, repeatCount, currentMonth, origNbDaysInMonth;
firStart = [firstRange startDate];
firEnd = [firstRange endDate];
rStart = [_r startDate];
rEnd = [_r endDate];
interval = [rrule repeatInterval];
@@ -71,33 +72,40 @@
// If rule is bound, check the bounds
if (![rrule isInfinite])
{
lastDate = nil;
lastStartDate = nil;
lastEndDate = nil;
until = [rrule untilDate];
repeatCount = [rrule repeatCount];
if (until)
{
lastDate = until;
lastStartDate = until;
lastEndDate = until;
}
if (repeatCount > 0)
{
if (lastDate == nil && ![rrule hasByMask])
if (lastStartDate == nil && ![rrule hasByMask])
{
// When there's no BYxxx mask, we can find the date of the last
// occurrence.
lastDate = [firStart dateByAddingYears: (interval * (repeatCount - 1))
lastStartDate = [firStart dateByAddingYears: (interval * (repeatCount - 1))
months: 0
days: 0];
lastEndDate = [firEnd dateByAddingYears: (interval * (repeatCount - 1))
months: 0
days: 0];
}
referenceDate = firStart;
}
if (lastDate != nil)
if (lastStartDate != nil)
{
if ([lastDate compare: rStart] == NSOrderedAscending)
if ([lastEndDate compare: rStart] == NSOrderedAscending)
// Range starts after last occurrence
return nil;
if ([lastDate compare: rEnd] == NSOrderedAscending)
if ([lastStartDate compare: rEnd] == NSOrderedAscending)
// Range ends after last occurence; adjust end date
rEnd = [lastDate addTimeInterval: [firstRange duration]];
rEnd = [lastStartDate addTimeInterval: [firstRange duration]];
}
}
@@ -0,0 +1,82 @@
"Inviting the following persons is prohibited:" = "다음 사람들을 초대하는 것은 금지되어 있습니다:";
"Personal Calendar" = "개인 캘린더";
vevent_class0 = "(공개 이벤트)";
vevent_class1 = "(비공개 이벤트)";
vevent_class2 = "(기밀 이벤트)";
vtodo_class0 = "(공개 할 일)";
vtodo_class1 = "(비공개 할 일)";
vtodo_class2 = "(기밀 할 일)";
/* Receipts */
"The event \"%{Summary}\" was created" = "이벤트 \"%{Summary}\"가 생성되었습니다";
"The event \"%{Summary}\" was deleted" = "이벤트 \"%{Summary}\"가 삭제되었습니다";
"The event \"%{Summary}\" was updated" = "이벤트 \"%{Summary}\"가 업데이트되었습니다";
"The task \"%{Summary}\" was created" = "할 일 \"%{Summary}\"이 생성되었습니다";
"The task \"%{Summary}\" was deleted" = "할 일 \"%{Summary}\"이 삭제되었습니다";
"The task \"%{Summary}\" was updated" = "할 일 \"%{Summary}\"이 업데이트되었습니다";
"The following attendees(s) were notified" = "다음 참석자에게 알림이 전송되었습니다";
"The following attendees(s) were added" = "다음 참석자가 추가되었습니다";
"The following attendees(s) were removed" = "다음 참석자가 제거되었습니다";
/* IMIP messages */
"calendar_label" = "캘린더";
"startDate_label" = "시작";
"endDate_label" = "종료";
"time_label" = "시간";
"to_label" = "까지";
"due_label" = "마감일";
"location_label" = "장소";
"summary_label" = "요약";
"comment_label" = "설명";
"organizer_label" = "주최자";
"attendee_label" = "참석자";
/* Invitation */
"Event Invitation: \"%{Summary}\"" = "이벤트 초대: \"%{Summary}\"";
"(sent by %{SentBy}) " = "(%{SentBy}님이 보냄) ";
"%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate}\nEnd: %{EndDate}\nDescription: %{Description}" = "%{Organizer} %{SentByText}님이 %{Summary}에 초대했습니다.\n\n시작: %{StartDate}\n종료: %{EndDate}\n설명: %{Description}";
"%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}" = "%{Organizer} %{SentByText}님이 %{Summary}에 초대했습니다.\n\n시작: %{StartDate} %{StartTime}\n종료: %{EndDate} %{EndTime}\n설명: %{Description}";
/* Deletion */
"Event Cancelled: \"%{Summary}\"" = "이벤트 취소됨: \"%{Summary}\"";
"%{Organizer} %{SentByText}has cancelled this event: %{Summary}.\n\nStart: %{StartDate}\nEnd: %{EndDate}\nDescription: %{Description}"
= "%{Organizer} %{SentByText}님이 이 이벤트를 취소했습니다: %{Summary}.\n\n시작: %{StartDate}\n종료: %{EndDate}\n설명: %{Description}";
"%{Organizer} %{SentByText}has cancelled this event: %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}"
= "%{Organizer} %{SentByText}님이 이 이벤트를 취소했습니다: %{Summary}.\n\n시작: %{StartDate} %{StartTime}\n종료: %{EndDate} %{EndTime}\n설명: %{Description}";
/* Update */
"The appointment \"%{Summary}\" for the %{OldStartDate} has changed"
= "%{OldStartDate}에 예정된 약속 \"%{Summary}\"이 변경되었습니다";
"The appointment \"%{Summary}\" for the %{OldStartDate} at %{OldStartTime} has changed"
= "%{OldStartDate} %{OldStartTime}에 예정된 약속 \"%{Summary}\"이 변경되었습니다";
"The following parameters have changed in the \"%{Summary}\" meeting:"
= "모임 \"%{Summary}\"에서 다음 매개변수가 변경되었습니다:";
"Please accept or decline those changes."
= "이 변경 사항을 수락하거나 거절하십시오.";
/* Reply */
"Accepted invitation: \"%{Summary}\"" = "초대 수락: \"%{Summary}\"";
"Declined invitation: \"%{Summary}\"" = "초대 거절: \"%{Summary}\"";
"Delegated invitation: \"%{Summary}\"" = "초대 위임: \"%{Summary}\"";
"Not yet decided on invitation: \"%{Summary}\"" = "초대에 대해 아직 결정하지 않음: \"%{Summary}\"";
"%{Attendee} %{SentByText}has accepted your event invitation."
= "%{Attendee} %{SentByText}님이 귀하의 이벤트 초대를 수락했습니다.";
"%{Attendee} %{SentByText}has declined your event invitation."
= "%{Attendee} %{SentByText}님이 귀하의 이벤트 초대를 거절했습니다.";
"%{Attendee} %{SentByText}has delegated the invitation to %{Delegate}."
= "%{Attendee} %{SentByText}님이 %{Delegate}에게 초대를 위임했습니다.";
"%{Attendee} %{SentByText}has not yet decided upon your event invitation."
= "%{Attendee} %{SentByText}님이 귀하의 이벤트 초대에 대해 아직 결정하지 않았습니다.";
/* Reminder */
"Reminder: \"%{Summary}\" - %{StartDate}" = "알림: \"%{Summary}\" - %{StartDate}";
/* Resources */
"Cannot access resource: \"%{Cn} %{SystemEmail}\"" = "리소스에 접근할 수 없습니다: \"%{Cn} %{SystemEmail}\"";
"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\". The conflicting event is \"%{EventTitle}\", and starts on %{StartDate}." = "리소스 \"%{Cn} %{SystemEmail}\"에 대한 최대 동시 예약 수(%{NumberOfSimultaneousBookings})에 도달했습니다. 충돌하는 이벤트는 \"%{EventTitle}\"이며, %{StartDate}에 시작합니다.";
/* Participation role */
"Your participation is required to this event" = "이 이벤트에 귀하의 참여가 필수입니다";
"Your participation is optional to this event" = "이 이벤트에 귀하의 참여는 선택 사항입니다";
"Your participation is not required to this event" = "이 이벤트에 귀하의 참여는 필요하지 않습니다";
@@ -0,0 +1,82 @@
"Inviting the following persons is prohibited:" = " ไม่เชิญบุคคลต่อไปนี้:";
"Personal Calendar" = "ปฏิทินส่วนตัว";
vevent_class0 = "(กิจกรรมสาธารณะ)";
vevent_class1 = "(กิจกรรมส่วนตัว)";
vevent_class2 = "(กิจกรรมลับ)";
vtodo_class0 = "(งานสาธารณะ)";
vtodo_class1 = "(งานส่วนตัว)";
vtodo_class2 = "(งานลับ)";
/* Receipts */
"The event \"%{Summary}\" was created" = "กิจกรรม \"%{Summary}\" ถุกสร้างขึ้น";
"The event \"%{Summary}\" was deleted" = "กิจกรรม \"%{Summary}\" ถูกลบ";
"The event \"%{Summary}\" was updated" = "กิจกรรม \"%{Summary}\" ถูกอัพเดต";
"The task \"%{Summary}\" was created" = "งาน \"%{Summary}\" ถูกสร้างขี้น";
"The task \"%{Summary}\" was deleted" = "งาน \"%{Summary}\" ถูกลบ";
"The task \"%{Summary}\" was updated" = "งาน \"%{Summary}\" ถูกอัพเดต";
"The following attendees(s) were notified" = "แจ้งผู้เข้าร่วมดังต่อไปนี้";
"The following attendees(s) were added" = "ผู้เข้าร่วมต่อไปนี้ถูกเพิ่มเข้ามา";
"The following attendees(s) were removed" = "ผู้เข้าร่วมต่อไปนี้ถูกลบออก";
/* IMIP messages */
"calendar_label" = "ปฏิทิน";
"startDate_label" = "เริ่ม";
"endDate_label" = "สิ้นสุด";
"time_label" = "เวลา";
"to_label" = "ถึง";
"due_label" = "วันครบกำหนด";
"location_label" = "สถานที่";
"summary_label" = "สรุป";
"comment_label" = "ความคิดเห็น";
"organizer_label" = "ผู้จัดงาน";
"attendee_label" = "ผู้เข้าร่วม";
/* Invitation */
"Event Invitation: \"%{Summary}\"" = "คำเชิญร่วมกิจกรรม : \"%{Summary}\"";
"(sent by %{SentBy}) " = "(ส่งโดย %{SentBy}) ";
"%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate}\nEnd: %{EndDate}\nDescription: %{Description}" = "%{Organizer} %{SentByText}ได้ทําการเชิญคุณไป %{Summary}.\n\nเริ่ม: %{StartDate}\nสิ้นสุด: %{EndDate}\nคำอธิบาย: %{Description}";
"%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}" = "%{Organizer} %{SentByText}ได้ทําการเชิญคุณไป %{Summary}.\n\nเริ่ม: %{StartDate} เวลา %{StartTime}\nสิ้นสุด: %{EndDate} เวลา %{EndTime}\nคำอธิบาย: %{Description}";
/* Deletion */
"Event Cancelled: \"%{Summary}\"" = "กิจกรรมถูกยกเลิกแล้ว: \"%{Summary}\"";
"%{Organizer} %{SentByText}has cancelled this event: %{Summary}.\n\nStart: %{StartDate}\nEnd: %{EndDate}\nDescription: %{Description}"
= "%{Organizer} %{SentByText}:ได้ยกเลิกกิจกรรม %{Summary}.\n\nเริ่ม: %{StartDate}\nสิ้นสุด: %{EndDate}\nคำอธิบาย: %{Description}";
"%{Organizer} %{SentByText}has cancelled this event: %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}"
= "%{Organizer} %{SentByText}hasได้ยกเลิกกิจกรรม: %{Summary}.\n\nเริ่ม: %{StartDate} เวลา %{StartTime}\nสิ้นสุด: %{EndDate} เวลา %{EndTime}\nคำอธิบาย: %{Description}";
/* Update */
"The appointment \"%{Summary}\" for the %{OldStartDate} has changed"
= "นัดหมาย \"%{Summary}\" สำหรับวันที่ %{OldStartDate} มีการเปลี่ยนแปลง";
"The appointment \"%{Summary}\" for the %{OldStartDate} at %{OldStartTime} has changed"
= "นัดหมาย \"%{Summary}\" สำหรับวันที่ %{OldStartDate} เวลา %{OldStartTime} มีการเปลี่ยนแปลง";
"The following parameters have changed in the \"%{Summary}\" meeting:"
= "มีการเปลี่ยนแปลงใน \"%{Summary}\" :";
"Please accept or decline those changes."
= "กรุณาตอบรับหรือปฏิเสธการเปลี่ยนแปลงเหล่านั้น";
/* Reply */
"Accepted invitation: \"%{Summary}\"" = "ตอบรับคำเชิญ: \"%{Summary}\"";
"Declined invitation: \"%{Summary}\"" = "ปฏิเสธคำเชิญ: \"%{Summary}\"";
"Delegated invitation: \"%{Summary}\"" = "ลบคำเชิญ: \"%{Summary}\"";
"Not yet decided on invitation: \"%{Summary}\"" = "ยังไม่ตัดสินใจเกี่ยวกับคำเชิญ: \"%{Summary}\"";
"%{Attendee} %{SentByText}has accepted your event invitation."
= "%{Attendee} %{SentByText} ได้ตอบรับคำเชิญกิจกรรมของคุณแล้ว";
"%{Attendee} %{SentByText}has declined your event invitation."
= "%{Attendee} %{SentByText} ได้ตอบปฏิเสธคำเชิญกิจกรรมของคุณแล้ว";
"%{Attendee} %{SentByText}has delegated the invitation to %{Delegate}."
= "%{Attendee} %{SentByText}ได้มอบหมายการเชิญให้ %{Delegate}.";
"%{Attendee} %{SentByText}has not yet decided upon your event invitation."
= "%{Attendee} %{SentByText}ยังไม่ได้ตัดสินใจเกี่ยวกับคำเชิญงานของคุณ";
/* Reminder */
"Reminder: \"%{Summary}\" - %{StartDate}" = "สิ่งเตือนความจำ: \"%{Summary}\" - %{StartDate}";
/* Resources */
"Cannot access resource: \"%{Cn} %{SystemEmail}\"" = "ไม่สามารถเข้าถึงทรัพยากรได้: \"%{Cn} %{SystemEmail}\"";
"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\". The conflicting event is \"%{EventTitle}\", and starts on %{StartDate}." = "จำนวนการจองสูงสุดพร้อมกัน (%{NumberOfSimultaneousBookings}) ขอใช้ทรัพยากร \"%{Cn} %{SystemEmail}\". งานที่ขัดแย้งกัน \"%{EventTitle}\", and starts on %{StartDate}.";
/* Participation role */
"Your participation is required to this event" = "การเข้าร่วมของคุณจำเป็นสำหรับกิจกรรมนี้";
"Your participation is optional to this event" = " การเข้าร่วมกิจกรรมนี้ไม่จำเป็น";
"Your participation is not required to this event" = " การเข้าร่วมของคุณไม่จำเป็นสำหรับกิจกรรมนี้";
@@ -0,0 +1,2 @@
"Personal Address Book" = "개인 주소록";
"Collected Address Book" = "받은/보낸 주소록";
@@ -0,0 +1,2 @@
"Personal Address Book" = "สมุดที่อยู่ส่วนตัว";
"Collected Address Book" = "สมุดที่อยู่ที่เก็บรวบรวม";
+4
View File
@@ -94,6 +94,8 @@ Mailer_RESOURCE_FILES += \
SOGoMailJapaneseReply.wo \
SOGoMailKazakhForward.wo \
SOGoMailKazakhReply.wo \
SOGoMailKoreanForward.wo \
SOGoMailKoreanReply.wo \
SOGoMailLatvianForward.wo \
SOGoMailLatvianReply.wo \
SOGoMailLithuanianForward.wo \
@@ -128,6 +130,8 @@ Mailer_RESOURCE_FILES += \
SOGoMailSpanishArgentinaReply.wo \
SOGoMailSwedishForward.wo \
SOGoMailSwedishReply.wo \
SOGoMailThaiForward.wo \
SOGoMailThaiReply.wo \
SOGoMailTurkishTurkeyForward.wo \
SOGoMailTurkishTurkeyReply.wo \
SOGoMailUkrainianForward.wo \
@@ -0,0 +1,5 @@
"OtherUsersFolderName" = "다른 사용자";
"SharedFoldersName" = "공유 폴더";
"Report: Marked messages as junk" = "보고서: 스팸으로 표시된 메시지";
"Report: Marked messages as not junk" = "보고서: 스팸이 아닌 것으로 표시된 메시지";
+6
View File
@@ -112,6 +112,9 @@
@interface SOGoMailKazakhForward : SOGoMailForward
@end
@interface SOGoMailKoreanForward : SOGoMailForward
@end
@interface SOGoMailLatvianForward : SOGoMailForward
@end
@@ -163,6 +166,9 @@
@interface SOGoMailSwedishForward : SOGoMailForward
@end
@interface SOGoMailThaiForward : SOGoMailForward
@end
@interface SOGoMailTurkishTurkeyForward : SOGoMailForward
@end
+6
View File
@@ -366,6 +366,9 @@
@implementation SOGoMailKazakhForward
@end
@implementation SOGoMailKoreanForward
@end
@implementation SOGoMailLatvianForward
@end
@@ -417,6 +420,9 @@
@implementation SOGoMailSwedishForward
@end
@implementation SOGoMailThaiForward
@end
@implementation SOGoMailTurkishTurkeyForward
@end
@@ -0,0 +1,15 @@
<#newLine/><#newLine
/><#signaturePlacementOnTop><#signature/><#newLine/><#newLine/></#signaturePlacementOnTop
>-------- 원본 메시지 --------<#newLine
/>제목: <#subject/><#newLine
/>날짜: <#date/><#newLine
/>보낸 사람: <#from/><#newLine
/><#hasReplyTo>회신: <#replyTo/><#newLine/></#hasReplyTo>
<#hasOrganization>조직: <#organization/><#newLine/></#hasOrganization>
받는 사람: <#to/>
<#hasCc>참조: <#cc/><#newLine/></#hasCc>
<#hasNewsGroups>뉴스그룹: <#newsgroups/><#newLine/></#hasNewsGroups>
<#hasReferences>참조: <#references/><#newLine/></#hasReferences>
<#newLine/><#newLine
/><#messageBody
/><#signaturePlacementOnBottom><#newLine/><#newLine/><#signature/></#signaturePlacementOnBottom>
@@ -0,0 +1,88 @@
subject: WOString {
value = subject;
escapeHTML = NO;
}
date: WOString {
value = date;
escapeHTML = NO;
}
from: WOString {
value = from;
escapeHTML = NO;
}
newLine: WOString {
value = newLine;
escapeHTML = NO;
}
hasReplyTo: WOConditional {
condition = hasReplyTo;
}
replyTo: WOString {
value = replyTo;
escapeHTML = NO;
}
hasOrganization: WOConditional {
condition = hasOrganization;
}
organization: WOString {
value = organization;
escapeHTML = NO;
}
to: WOString {
value = to;
escapeHTML = NO;
}
hasCc: WOConditional {
condition = hasCc;
}
cc: WOString {
value = cc;
escapeHTML = NO;
}
hasNewsGroups: WOConditional {
condition = hasNewsGroups;
}
newsgroups: WOString {
value = newsgroups;
escapeHTML = NO;
}
hasReferences: WOConditional {
condition = hasReferences;
}
references: WOString {
value = references;
escapeHTML = NO;
}
messageBody: WOString {
value = messageBody;
escapeHTML = NO;
}
signature: WOString {
value = signature;
escapeHTML = NO;
}
signaturePlacementOnTop: WOConditional {
condition = signaturePlacementOnTop;
}
signaturePlacementOnBottom: WOConditional {
condition = signaturePlacementOnTop;
negate = YES;
}
@@ -0,0 +1,20 @@
<#replyPlacementOnTop><#newLine/><#newLine/></#replyPlacementOnTop>
<#signaturePlacementOnTop><#signature/><#newLine/><#newLine/></#signaturePlacementOnTop>
<#outlookMode>
-------- 원본 메시지 --------
제목: <#subject/><#newLine/>
날짜: <#date/><#newLine/>
보낸 사람: <#from/><#newLine/>
<#hasReplyTo>회신: <#replyTo/><#newLine/></#hasReplyTo>
<#hasOrganization>조직: <#organization/><#newLine/></#hasOrganization>
받는 사람: <#to/><#newLine/>
<#hasCc>참조: <#cc/><#newLine/></#hasCc>
<#hasNewsGroups>뉴스그룹: <#newsgroups/><#newLine/></#hasNewsGroups>
<#hasReferences>참조: <#references/><#newLine/></#hasReferences>
</#outlookMode>
<#standardMode>
<#date/>에 <#from/>(이)가 작성했습니다:
</#standardMode>
<#newLine/><#newLine/><#messageBody/>
<#replyPlacementOnBottom><#newLine/><#newLine/></#replyPlacementOnBottom>
<#signaturePlacementOnBottom><#newLine/><#signature/></#signaturePlacementOnBottom>
@@ -0,0 +1,106 @@
outlookMode: WOConditional {
condition = outlookMode;
}
standardMode: WOConditional {
condition = outlookMode;
negate = YES;
}
subject: WOString {
value = subject;
escapeHTML = NO;
}
date: WOString {
value = date;
escapeHTML = NO;
}
from: WOString {
value = from;
escapeHTML = NO;
}
newLine: WOString {
value = newLine;
escapeHTML = NO;
}
hasReplyTo: WOConditional {
condition = hasReplyTo;
}
replyTo: WOString {
value = replyTo;
escapeHTML = NO;
}
hasOrganization: WOConditional {
condition = hasOrganization;
}
organization: WOString {
value = organization;
escapeHTML = NO;
}
to: WOString {
value = to;
escapeHTML = NO;
}
hasCc: WOConditional {
condition = hasCc;
}
cc: WOString {
value = cc;
escapeHTML = NO;
}
hasNewsGroups: WOConditional {
condition = hasNewsGroups;
}
newsgroups: WOString {
value = newsgroups;
escapeHTML = NO;
}
hasReferences: WOConditional {
condition = hasReferences;
}
references: WOString {
value = references;
escapeHTML = NO;
}
messageBody: WOString {
value = messageBody;
escapeHTML = NO;
}
signature: WOString {
value = signature;
escapeHTML = NO;
}
replyPlacementOnTop: WOConditional {
condition = replyPlacementOnTop;
}
replyPlacementOnBottom: WOConditional {
condition = replyPlacementOnTop;
negate = YES;
}
signaturePlacementOnTop: WOConditional {
condition = signaturePlacementOnTop;
}
signaturePlacementOnBottom: WOConditional {
condition = signaturePlacementOnTop;
negate = YES;
}
+6
View File
@@ -108,6 +108,9 @@
@interface SOGoMailJapaneseReply : SOGoMailReply
@end
@interface SOGoMailKoreanReply : SOGoMailReply
@end
@interface SOGoMailKazakhReply : SOGoMailReply
@end
@@ -162,6 +165,9 @@
@interface SOGoMailSwedishReply : SOGoMailReply
@end
@interface SOGoMailThaiReply : SOGoMailReply
@end
@interface SOGoMailTurkishTurkeyReply : SOGoMailReply
@end
+6
View File
@@ -167,6 +167,9 @@
@implementation SOGoMailKazakhReply
@end
@implementation SOGoMailKoreanReply
@end
@implementation SOGoMailLatvianReply
@end
@@ -218,6 +221,9 @@
@implementation SOGoMailSwedishReply
@end
@implementation SOGoMailThaiReply
@end
@implementation SOGoMailTurkishTurkeyReply
@end
@@ -0,0 +1,15 @@
<#newLine/><#newLine
/><#signaturePlacementOnTop><#signature/><#newLine/><#newLine/></#signaturePlacementOnTop
>-------- ข้อความต้นทาง --------<#newLine
/>หัวข้อ: <#subject/><#newLine
/>วันที่: <#date/><#newLine
/>จาก: <#from/><#newLine
/><#hasReplyTo>ตอบกลับ: <#replyTo/><#newLine/></#hasReplyTo
><#hasOrganization>องค์กร: <#organization/><#newLine/></#hasOrganization
>ถึง: <#to/><#newLine
/><#hasCc>สำเนา: <#cc/><#newLine/></#hasCc
><#hasNewsGroups>กลุ่มข่าว: <#newsgroups/><#newLine/></#hasNewsGroups
><#hasReferences>การอ้างถึง: <#references/><#newLine/></#hasReferences
><#newLine/><#newLine
/><#messageBody
/><#signaturePlacementOnBottom><#newLine/><#newLine/><#signature/></#signaturePlacementOnBottom>
@@ -0,0 +1,88 @@
subject: WOString {
value = subject;
escapeHTML = NO;
}
date: WOString {
value = date;
escapeHTML = NO;
}
from: WOString {
value = from;
escapeHTML = NO;
}
newLine: WOString {
value = newLine;
escapeHTML = NO;
}
hasReplyTo: WOConditional {
condition = hasReplyTo;
}
replyTo: WOString {
value = replyTo;
escapeHTML = NO;
}
hasOrganization: WOConditional {
condition = hasOrganization;
}
organization: WOString {
value = organization;
escapeHTML = NO;
}
to: WOString {
value = to;
escapeHTML = NO;
}
hasCc: WOConditional {
condition = hasCc;
}
cc: WOString {
value = cc;
escapeHTML = NO;
}
hasNewsGroups: WOConditional {
condition = hasNewsGroups;
}
newsgroups: WOString {
value = newsgroups;
escapeHTML = NO;
}
hasReferences: WOConditional {
condition = hasReferences;
}
references: WOString {
value = references;
escapeHTML = NO;
}
messageBody: WOString {
value = messageBody;
escapeHTML = NO;
}
signature: WOString {
value = signature;
escapeHTML = NO;
}
signaturePlacementOnTop: WOConditional {
condition = signaturePlacementOnTop;
}
signaturePlacementOnBottom: WOConditional {
condition = signaturePlacementOnTop;
negate = YES;
}
@@ -0,0 +1,18 @@
<#replyPlacementOnTop><#newLine/><#newLine/></#replyPlacementOnTop
><#signaturePlacementOnTop><#signature/><#newLine/><#newLine/></#signaturePlacementOnTop
><#outlookMode
>-------- ข้อความต้นทาง --------<#newLine
/>หัวข้อ: <#subject/><#newLine
/>วันที่: <#date/><#newLine
/>จาก: <#from/><#newLine
/><#hasReplyTo>ตอบกลับ: <#replyTo/><#newLine/></#hasReplyTo
><#hasOrganization>องค์กร: <#organization/><#newLine/></#hasOrganization
>ถึง: <#to/><#newLine
/><#hasCc>สำเนา: <#cc/><#newLine/></#hasCc
><#hasNewsGroups>กลุ่มข่าว: <#newsgroups/><#newLine/></#hasNewsGroups
><#hasReferences>การอ้างถึง: <#references/><#newLine/></#hasReferences
></#outlookMode
><#standardMode>บน <#date/>, <#from/> ขียน:</#standardMode
><#newLine/><#newLine/><#messageBody
/><#replyPlacementOnBottom><#newLine/><#newLine/></#replyPlacementOnBottom
><#signaturePlacementOnBottom><#newLine/><#signature/></#signaturePlacementOnBottom>
@@ -0,0 +1,106 @@
outlookMode: WOConditional {
condition = outlookMode;
}
standardMode: WOConditional {
condition = outlookMode;
negate = YES;
}
subject: WOString {
value = subject;
escapeHTML = NO;
}
date: WOString {
value = date;
escapeHTML = NO;
}
from: WOString {
value = from;
escapeHTML = NO;
}
newLine: WOString {
value = newLine;
escapeHTML = NO;
}
hasReplyTo: WOConditional {
condition = hasReplyTo;
}
replyTo: WOString {
value = replyTo;
escapeHTML = NO;
}
hasOrganization: WOConditional {
condition = hasOrganization;
}
organization: WOString {
value = organization;
escapeHTML = NO;
}
to: WOString {
value = to;
escapeHTML = NO;
}
hasCc: WOConditional {
condition = hasCc;
}
cc: WOString {
value = cc;
escapeHTML = NO;
}
hasNewsGroups: WOConditional {
condition = hasNewsGroups;
}
newsgroups: WOString {
value = newsgroups;
escapeHTML = NO;
}
hasReferences: WOConditional {
condition = hasReferences;
}
references: WOString {
value = references;
escapeHTML = NO;
}
messageBody: WOString {
value = messageBody;
escapeHTML = NO;
}
signature: WOString {
value = signature;
escapeHTML = NO;
}
replyPlacementOnTop: WOConditional {
condition = replyPlacementOnTop;
}
replyPlacementOnBottom: WOConditional {
condition = replyPlacementOnTop;
negate = YES;
}
signaturePlacementOnTop: WOConditional {
condition = signaturePlacementOnTop;
}
signaturePlacementOnBottom: WOConditional {
condition = signaturePlacementOnTop;
negate = YES;
}
@@ -0,0 +1,5 @@
"OtherUsersFolderName" = "ผู้ใช้งานอื่นๆ";
"SharedFoldersName" = "โฟลเดอร์ที่แชร์";
"Report: Marked messages as junk" = "รายงาน: ทำเครื่องหมายข้อความเป็นขยะ";
"Report: Marked messages as not junk" = "รายงาน: ทำเครื่องหมายข้อความว่าไม่ใช่ขยะ";
+1 -1
View File
@@ -231,7 +231,7 @@ endif
ADDITIONAL_TOOL_LIBS += -Lobj -lSOGo$(LIBRARY_NAME_SUFFIX)
ADDITIONAL_INCLUDE_DIRS += -I../../SOPE/
ADDITIONAL_LIB_DIRS += -L../../SOPE/GDLContentStore/obj/
ADDITIONAL_LDFLAGS += -lmemcached -lzip -lytnef
ADDITIONAL_LDFLAGS += -lmemcached -lzip -lytnef -lcurl
-include GNUmakefile.preamble
ifneq ($(FHS_INSTALL_ROOT),)
+2
View File
@@ -66,6 +66,7 @@
"Italian",
"Japanese",
"Kazakh",
"Korean",
"Latvian",
"Lithuanian",
"Macedonian",
@@ -84,6 +85,7 @@
"SpanishArgentina",
"SpanishSpain",
"Swedish",
"Thai",
"TurkishTurkey",
"Ukrainian",
"Welsh"
+22 -2
View File
@@ -33,6 +33,25 @@
@class NSURL;
@class NSJSONSerialization;
size_t curl_body_function(void *ptr, size_t size, size_t nmemb, void *buffer);
@interface SimpleOpenIdResponse: NSObject
{
unsigned int status;
NSString *content;
NSString *headers;
}
- (id)initWithResponse: (NSString *)_data andHeaders: (NSString *)_headers andStatus:(unsigned int )_status;
- (void)setStatus:(unsigned int)_status;
- (unsigned int)status;
- (void)setContent:(NSString *)_data;
- (NSString *)contentString;
- (void)setHearders:(NSString *)_data;
- (NSString *)headers;
@end
@interface SOGoOpenIdSession : SOGoObject
{
@@ -47,6 +66,7 @@
NSString *openIdClient;
NSString *openIdClientSecret;
NSString *openIdEmailParam;
NSString *openIdHttpVersion;
BOOL openIdEnableRefreshToken;
BOOL sendDomainInfo;
@@ -80,12 +100,12 @@
- (void) initialize;
- (void) initializeWithConfig: (NSDictionary *) _config;
- (BOOL) sessionIsOK;
- (WOResponse *) _performOpenIdRequest: (NSString *) endpoint
- (SimpleOpenIdResponse *) _performOpenIdRequest: (NSString *) endpoint
method: (NSString *) method
headers: (NSDictionary *) headers
body: (NSData *) body;
- (NSMutableDictionary *) fecthConfiguration: (NSString *) _domain;
- (void) setAccessToken;
- (void) setAccessToken: (NSString* ) token;
- (NSString *) getRefreshToken;
- (NSString *) getToken;
- (NSString *) getCurrentToken;
+233 -52
View File
@@ -18,8 +18,11 @@
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSProcessInfo.h>
#import <curl/curl.h>
#import <NGObjWeb/WOHTTPConnection.h>
#import <NGObjWeb/WORequest.h>
#import <NGObjWeb/WOResponse.h>
@@ -27,12 +30,12 @@
#import <SOGo/SOGoUser.h>
#import <GDLContentStore/GCSOpenIdFolder.h>
#import <GDLContentStore/GCSFolderManager.h>
#import "NSDictionary+Utilities.h"
#import "NSString+Utilities.h"
#import <SOGo/NSString+Utilities.h>
#import <SOGo/NSString+Crypto.h>
#import "SOGoCache.h"
#import "SOGoSystemDefaults.h"
@@ -40,6 +43,88 @@
static BOOL SOGoOpenIDDebugEnabled = YES;
size_t curl_body_function(void *ptr, size_t size, size_t nmemb, void *buffer)
{
size_t total;
total = size * nmemb;
[(NSMutableData *)buffer appendBytes: ptr length: total];
return total;
}
@implementation SimpleOpenIdResponse
- (id)init {
if ((self = [super init])) {
}
return self;
}
- (id)initWithResponse: (NSString *)_data andHeaders: (NSString *)_headers andStatus:(unsigned int )_status{
if ((self = [self init])) {
[self setStatus: _status];
[self setContent: _data];
[self setHeaders: _headers];
}
return self;
}
- (void)setStatus:(unsigned int)_status
{
self->status = _status;
}
- (unsigned int)status
{
if(self->status)
return self->status;
return 0;
}
- (void)setContent:(NSString *)_data
{
self->content = _data;
}
- (NSString *)contentString
{
if(self->content)
return self->content;
return nil;
}
- (void)setHeaders:(NSString *)_data
{
self->headers = _data;
}
- (NSString *)headers
{
if(self->headers)
return self->headers;
return nil;
}
- (NSString*)description {
NSString *co, *hd;
unsigned int st;
st = 0;
co = @"nil";
hd = @"nil";
if(self->status)
st = self->status;
if(self->headers)
hd = self->headers;
if(self->content)
co = self->content;
return [NSString stringWithFormat: @"<SimpleOpenIdResponse> <status: %d>, <headers: %@>, <content: %@>", st, hd, co];
}
@end
@implementation SOGoOpenIdSession
/// Check if all required parameters to set up a OpenIdSession are in sogo.conf
@@ -54,6 +139,13 @@ static BOOL SOGoOpenIDDebugEnabled = YES;
return NO;
}
sd = [SOGoSystemDefaults sharedSystemDefaults];
if(![[sd authenticationType] isEqualToString: @"openid"])
{
[self errorWithFormat: @"Sogo SOGoAuthenticationType is not openid"];
return NO;
}
return ([sd openIdConfigUrl] && [sd openIdScope] && [sd openIdClient] && [sd openIdClientSecret]);
}
@@ -72,6 +164,7 @@ static BOOL SOGoOpenIDDebugEnabled = YES;
openIdClient = [_config objectForKey: @"SOGoOpenIdClient"];
openIdClientSecret = [_config objectForKey: @"SOGoOpenIdClientSecret"];
openIdEmailParam = [_config objectForKey: @"SOGoOpenIdEmailParam"];
openIdHttpVersion = [_config objectForKey: @"SOGoOpenIdHttpVersion"];
openIdEnableRefreshToken = NO;
refreshTokenBool = [_config objectForKey: @"SOGoOpenIdEnableRefreshToken"];
@@ -120,7 +213,7 @@ static BOOL SOGoOpenIDDebugEnabled = YES;
}
else
{
[self errorWithFormat: @"Missing parameters from sogo.conf"];
[self errorWithFormat: @"LoginTypebyDOmain - Openid not found or missing parameters for domain", _domain];
}
}
else if ([[self class] checkUserConfig])
@@ -130,6 +223,7 @@ static BOOL SOGoOpenIDDebugEnabled = YES;
openIdClient = [sd openIdClient];
openIdClientSecret = [sd openIdClientSecret];
openIdEmailParam = [sd openIdEmailParam];
openIdHttpVersion = [sd openIdHttpVersion];
openIdEnableRefreshToken = [sd openIdEnableRefreshToken];
userTokenInterval = [sd openIdTokenCheckInterval];
sendDomainInfo = [sd openIdSendDomainInfo];
@@ -149,66 +243,147 @@ static BOOL SOGoOpenIDDebugEnabled = YES;
}
}
- (WOResponse *) _performOpenIdRequest: (NSString *) endpoint
- (SimpleOpenIdResponse *) _performOpenIdRequest: (NSString *) endpoint
method: (NSString *) method
headers: (NSDictionary *) headers
body: (NSData *) body
{
NSURL *url;
NSMutableData *buffer, *buffHeaders;
SimpleOpenIdResponse *response;
CURL *curl;
struct curl_slist *headerlist=NULL;
NSUInteger status;
WORequest *request;
WOResponse *response;
WOHTTPConnection *httpConnection;
url = [NSURL URLWithString: endpoint];
if (url)
{
if(SOGoOpenIDDebugEnabled)
{
NSLog(@"OpenId perform request: %@ %@", method, endpoint);
NSLog(@"OpenId perform request, headers %@", headers);
// if(body)
// NSLog(@"OpenId perform request: content %@", [[NSString alloc] initWithData:body encoding:NSUTF8StringEncoding]);
}
httpConnection = [[WOHTTPConnection alloc] initWithURL: url];
[httpConnection autorelease];
NSString *content, *headerResp;
CURLcode rc;
char error[CURL_ERROR_SIZE];
request = [[WORequest alloc] initWithMethod: method
uri: [endpoint hostlessURL]
httpVersion: @"HTTP/1.1"
headers: headers content: body
userInfo: nil];
[request autorelease];
[httpConnection sendRequest: request];
response = [httpConnection readResponse];
status = [response status];
if(status >= 200 && status <500 && status != 404)
return response;
else if (status == 404)
{
[self errorWithFormat: @"OpenID endpoint not found (404): %@", endpoint];
return nil;
}
else
{
[self errorWithFormat: @"OpenID server internal error during %@: %@", endpoint, response];
return nil;
}
}
else
url = [NSURL URLWithString: endpoint];
if(!url)
{
[self errorWithFormat: @"OpenID can't handle endpoint (not a url): '%@'", endpoint];
return nil;
}
if(SOGoOpenIDDebugEnabled)
{
NSLog(@"OpenId perform request: %@ %@", method, endpoint);
NSLog(@"OpenId perform request, headers %@", headers);
}
if(SOGoOpenIDDebugEnabled)
NSLog(@"OpenId perform request, body raw %@", body);
curl_global_init(CURL_GLOBAL_SSL);
curl = curl_easy_init();
if (curl)
{
error[0] = 0;
curl_easy_setopt(curl, CURLOPT_URL, [endpoint UTF8String]);
//add form
if(body)
{
//Trick because sometimes NSData bytes don't add the \0 at the end and junk character may be added
const char *myBodyTmp = (const char*)[body bytes];
char myBody[[body length]+1];
strncpy(myBody, myBodyTmp, [body length]);
myBody[[body length]]='\0';
if(SOGoOpenIDDebugEnabled)
NSLog(@"OpenId perform request, myBodyTmp %s", myBodyTmp);
if(SOGoOpenIDDebugEnabled)
NSLog(@"OpenId perform request, myBody %s", myBody);
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, myBody);
}
//add headers
if(headers)
{
NSEnumerator *enumerator = [headers keyEnumerator];
NSString *key, *header;
while((key = [enumerator nextObject]))
{
header = [NSString stringWithFormat: @"%@: %@", key, [headers objectForKey: key]];
headerlist = curl_slist_append(headerlist, [header UTF8String]);
}
}
if(headerlist != NULL)
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
buffer = [NSMutableData data];
buffHeaders = [NSMutableData data];
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_body_function);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, buffer);
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, curl_body_function);
curl_easy_setopt(curl, CURLOPT_HEADERDATA, buffHeaders);
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error);
// Perform SOAP request
rc = curl_easy_perform(curl);
if (rc == CURLE_OK)
{
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status);
response = [SimpleOpenIdResponse alloc];
headerResp = [[NSString alloc] initWithData: buffHeaders
encoding: NSUTF8StringEncoding];
response = [response initWithResponse: nil andHeaders: headerResp andStatus: status];
if(status >= 200 && status <500 && status != 404)
{
content = [[NSString alloc] initWithData: buffer
encoding: NSUTF8StringEncoding];
if (!content)
content = [[NSString alloc] initWithData: buffer
encoding: NSISOLatin1StringEncoding];
[response setContent: content];
if(SOGoOpenIDDebugEnabled)
NSLog(@"OpenId perform request: response is: %@", response);
return [response autorelease];
}
else if (status == 404)
{
[self errorWithFormat: @"OpenID endpoint not found (404): %@", endpoint];
return nil;
}
else
{
[self errorWithFormat: @"OpenID server internal error during %@: %@", endpoint, response];
return nil;
}
}
else
{
[self errorWithFormat: @"CURL error while accessing %@ (%d): %@", endpoint, rc,
[NSString stringWithCString: strlen(error) ? error : curl_easy_strerror(rc)]];
}
curl_easy_cleanup (curl);
}
else
{
[self errorWithFormat: @"OpenID error when setting curl request for: %@", endpoint];
return nil;
}
}
- (NSMutableDictionary *) fecthConfiguration: (NSString*) _domain
{
NSString *content;
WOResponse * response;
SimpleOpenIdResponse *response;
// WOResponse * response;
NSUInteger status;
NSMutableDictionary *result;
NSDictionary *config, *headers;
@@ -498,7 +673,8 @@ static BOOL SOGoOpenIDDebugEnabled = YES;
- (NSMutableDictionary *) fetchToken: (NSString * ) code redirect: (NSString *) oldLocation
{
NSString *location, *form, *content;
WOResponse *response;
SimpleOpenIdResponse *response;
// WOResponse *response;
NSUInteger status;
NSMutableDictionary *result;
NSDictionary *headers;
@@ -523,7 +699,10 @@ static BOOL SOGoOpenIDDebugEnabled = YES;
self->forDomain, @"sogo-user-domain", nil];
else
headers = [NSDictionary dictionaryWithObject: @"application/x-www-form-urlencoded" forKey: @"content-type"];
if(SOGoOpenIDDebugEnabled)
NSLog(@"OpenId fetch token, form %@", form);
response = [self _performOpenIdRequest: location
method: @"POST"
headers: headers
@@ -566,7 +745,8 @@ static BOOL SOGoOpenIDDebugEnabled = YES;
- (NSMutableDictionary *) refreshToken: (NSString * ) userRefreshToken
{
NSString *location, *form, *content;
WOResponse *response;
SimpleOpenIdResponse *response;
// WOResponse *response;
NSUInteger status;
NSMutableDictionary *result;
NSDictionary *headers;
@@ -639,7 +819,8 @@ static BOOL SOGoOpenIDDebugEnabled = YES;
- (NSMutableDictionary *) fetchUserInfo
{
NSString *location, *auth, *content;
WOResponse *response;
SimpleOpenIdResponse *response;
// WOResponse *response;
NSUInteger status;
NSMutableDictionary *result;
NSDictionary *profile, *headers;
@@ -695,7 +876,7 @@ static BOOL SOGoOpenIDDebugEnabled = YES;
}
else
{
[self logWithFormat: @"Error during fetching the token (status %d), response: %@", status, response];
[self logWithFormat: @"Error fetching userInfo (status %d), response: %@", status, response];
[result setObject: @"http-error" forKey: @"error"];
}
}
+18 -18
View File
@@ -122,28 +122,28 @@ static NSString *productDirectoryName = @"SOGo";
pathes = [[self productSearchPathes] objectEnumerator];
while ((lpath = [pathes nextObject]))
{
productNames = [[fm directoryContentsAtPath: lpath] objectEnumerator];
while ((productName = [productNames nextObject]))
{
productNames = [[fm directoryContentsAtPath: lpath] objectEnumerator];
while ((productName = [productNames nextObject]))
{
if ([[productName pathExtension] isEqualToString: @"SOGo"])
{
bpath = [lpath stringByAppendingPathComponent: productName];
[registry registerProductAtPath: bpath];
[loadedProducts addObject: productName];
}
}
if ([loadedProducts count])
if ([[productName pathExtension] isEqualToString: @"SOGo"])
{
if (verbose)
{
[self logWithFormat: @"SOGo products loaded from '%@':", lpath];
[self logWithFormat: @" %@",
[loadedProducts componentsJoinedByString: @", "]];
}
[loadedProducts removeAllObjects];
bpath = [lpath stringByAppendingPathComponent: productName];
[registry registerProductAtPath: bpath];
[loadedProducts addObject: productName];
}
}
if ([loadedProducts count])
{
if (verbose)
{
[self logWithFormat: @"SOGo products loaded from '%@':", lpath];
[self logWithFormat: @" %@",
[loadedProducts componentsJoinedByString: @", "]];
}
[loadedProducts removeAllObjects];
}
}
if (![registry loadAllProducts] && verbose)
[self warnWithFormat: @"could not load all products !"];
+28 -3
View File
@@ -162,11 +162,23 @@
// Get the key length and its bytes
data = [theKey dataByDecodingBase64];
key = (char *)[data bytes];
klen = [data length];
//value longer than the key, concatenate the key with itself until long enough
if (klen < [theValue length])
[self errorWithFormat: @"Value to be secured is too big (%i > %i) -- secured value will be corrupted", [theValue length], klen, [theKey length]];
{
NSMutableData *concatenatedData = [NSMutableData data];
int j;
int nbDuplication = [theValue length]/klen;
for(j=0; j <= nbDuplication; j++)
[concatenatedData appendData:data];
data = [NSData dataWithData: concatenatedData];
klen = [data length];
}
key = (char *)[data bytes];
// Get the key - padding it with 0 with key length
pass = (char *) calloc(klen, sizeof(char));
@@ -201,7 +213,6 @@
// Get the key length and its bytes
dataKey = [theKey dataByDecodingBase64];
key = (char *)[dataKey bytes];
klen = [dataKey length];
// Get the secured value length and its bytes
@@ -209,6 +220,20 @@
value = (char *)[dataValue bytes];
vlen = [dataValue length];
//If the key is shorer than the value, duplicate it with itself.
if(klen < vlen)
{
NSMutableData *concatenatedData = [NSMutableData data];
int j;
int nbDuplication = [dataValue length]/klen;
for(j=0; j <= nbDuplication; j++)
[concatenatedData appendData:dataKey];
dataKey = [NSData dataWithData: concatenatedData];
klen = [dataKey length];
}
key = (char *)[dataKey bytes];
// Target buffer
buf = (char *) calloc(klen, sizeof(char));
+9 -1
View File
@@ -496,6 +496,7 @@ static NSString *sieveScriptName = @"sogo";
}
- (NSString *) _extractSieveAction: (NSDictionary *) action
withReq: (NSMutableDictionary *) req
delimiter: (NSString *) delimiter
{
NSString *sieveAction, *method, *requirement, *argument, *flag, *mailbox;
@@ -548,7 +549,9 @@ static NSString *sieveScriptName = @"sogo";
{
argument = [NSString stringWithFormat: @"mailto:%@", argument];
sieveAction = [NSString stringWithFormat: @"%@ %@",
method, [argument asSieveQuotedString]];
method, [argument asSieveQuotedString]];
[req addObjectUniquely: @"enotify"];
[req addObjectUniquely: @"variables"];
}
else if ([method isEqualToString: @"reject"])
sieveAction = [NSString stringWithFormat: @"%@ %@",
@@ -575,6 +578,7 @@ static NSString *sieveScriptName = @"sogo";
}
- (NSArray *) _extractSieveActions: (NSArray *) actions
withReq: (NSMutableDictionary *) req
delimiter: (NSString *) delimiter
{
NSMutableArray *sieveActions;
@@ -586,6 +590,7 @@ static NSString *sieveScriptName = @"sogo";
for (count = 0; !scriptError && count < max; count++)
{
sieveAction = [self _extractSieveAction: [actions objectAtIndex: count]
withReq: req
delimiter: delimiter];
if (!scriptError)
[sieveActions addObject: sieveAction];
@@ -595,6 +600,7 @@ static NSString *sieveScriptName = @"sogo";
}
- (NSString *) _convertScriptToSieve: (NSDictionary *) newScript
withReq: (NSMutableDictionary *) req
delimiter: (NSString *) delimiter
{
NSMutableString *sieveText;
@@ -624,6 +630,7 @@ static NSString *sieveScriptName = @"sogo";
scriptError = [NSString stringWithFormat: @"Bad test: %@", match];
}
sieveActions = [self _extractSieveActions: [newScript objectForKey: @"actions"]
withReq: req
delimiter: delimiter];
if ([sieveActions count])
[sieveText appendFormat: @" %@;\r\n",
@@ -660,6 +667,7 @@ static NSString *sieveScriptName = @"sogo";
if ([[currentScript objectForKey: @"active"] boolValue])
{
sieveText = [self _convertScriptToSieve: currentScript
withReq: newRequirements
delimiter: delimiter];
[sieveScript appendString: sieveText];
}
+2
View File
@@ -83,6 +83,7 @@ static const NSString *kDisableSharingCalendar = @"Calendar";
- (BOOL) uixDebugEnabled;
- (BOOL) easDebugEnabled;
- (BOOL) openIdDebugEnabled;
- (BOOL) apiDebugEnabled;
- (BOOL) tnefDecoderDebugEnabled;
- (BOOL) xsrfValidationEnabled;
@@ -106,6 +107,7 @@ NSComparisonResult languageSort(id el1, id el2, void *context);
- (NSString *) openIdClient;
- (NSString *) openIdClientSecret;
- (NSString *) openIdEmailParam;
- (NSString *) openIdHttpVersion;
- (BOOL) openIdEnableRefreshToken;
- (BOOL) openIdLogoutEnabled: (NSString *) _domain;
- (int) openIdTokenCheckInterval;
+14
View File
@@ -654,6 +654,11 @@ _injectConfigurationFromFile (NSMutableDictionary *defaultsDict,
return [self boolForKey: @"SOGoOpenIDDebugEnabled"];
}
- (BOOL) apiDebugEnabled
{
return [self boolForKey: @"SOGoAPIDebugEnabled"];
}
- (BOOL) tnefDecoderDebugEnabled
{
return [self boolForKey: @"SOGoTnefDecoderDebugEnabled"];
@@ -779,6 +784,15 @@ NSComparisonResult languageSort(id el1, id el2, void *context)
return emailParam;
}
- (NSString *) openIdHttpVersion
{
NSString *httpVersion;
httpVersion = [self stringForKey: @"SOGoOpenIdHttpVersion"];
if(!httpVersion)
httpVersion = @"HTTP/1.1";
return httpVersion;
}
- (BOOL) openIdLogoutEnabled: (NSString *) _domain
{
if(_domain && [self doesLoginTypeByDomain])
@@ -25,7 +25,7 @@
"No resource" = "Geen middelen";
"Any Authenticated User" = "Elke geauthenticeerde gebruiker";
"Public Access" = "Publieke toegang";
"Save" = "Save";
"Clear" = "Clear";
"Message of the day" = "Message of the day";
"Message of the day has been saved" = "Message of the day has been saved";
"Save" = "Opslaan";
"Clear" = "Leeg maken";
"Message of the day" = "Bericht van de dag";
"Message of the day has been saved" = "Bericht van de dag is opgeslagen";
@@ -0,0 +1,31 @@
/* this file is in UTF-8 format! */
"Help" = "도움말";
"Close" = "닫기";
"Modules" = "모듈";
/* Modules short names */
"ACLs" = "ACL";
/* Modules titles */
"ACLs_title" = "사용자 폴더 ACL 관리";
/* Modules descriptions */
"ACLs_description" = "<p>접근 제어 목록(ACL) 관리 모듈은 각 사용자의 캘린더 및 주소록의 ACL을 변경할 수 있도록 합니다.</p><p>사용자 폴더의 ACL을 수정하려면 창 상단의 검색 필드에 사용자 이름을 입력하고 원하는 폴더를 두 번 클릭하십시오.</p>";
"Name or Email" = "이름 또는 이메일";
"ACLs saved" = "ACL 저장됨";
/* Rights module: initial search message */
"Start a search to edit the rights" = "권한을 편집하려면 검색을 시작하십시오";
/* Rights module: Empty search result */
"No matching user" = "일치하는 사용자 없음";
/* Rights module: no selection */
"No resource selected" = "선택된 리소스 없음";
"Add User" = "사용자 추가";
"Subscribe User" = "사용자 구독";
"Rights" = "권한";
"Search Users" = "사용자 검색";
"users found" = "사용자 발견";
"No resource" = "리소스 없음";
"Any Authenticated User" = "모든 인증된 사용자";
"Public Access" = "공개 접근";
"Save" = "저장";
"Clear" = "지우기";
"Message of the day" = "오늘의 메시지";
"Message of the day has been saved" = "오늘의 메시지가 저장되었습니다";
@@ -0,0 +1,31 @@
/* this file is in UTF-8 format! */
"Help" = "ช่วยเหลือ";
"Close" = "ปิด";
"Modules" = "โมดูล";
/* Modules short names */
"ACLs" = "ACLs";
/* Modules titles */
"ACLs_title" = "Users folders ACLs management";
/* Modules descriptions */
"ACLs_description" = "<p>โมดูลการจัดการรายการควบคุมการเข้าถึงช่วยให้สามารถเปลี่ยนแปลง ACLs ของปฏิทินและสมุดที่อยู่ของผู้ใช้แต่ละคนได้</p><p>ในการแก้ไข ACLs ของโฟลเดอร์ของผู้ใช้ ให้พิมพ์ชื่อผู้ใช้ในช่องค้นหาที่ด้านบนของหน้าต่างและดับเบิลคลิกที่โฟลเดอร์ที่ต้องการ</p>";
"Name or Email" = "ชื่อหรืออีเมล์";
"ACLs saved" = "ACLs บันทึกแล้ว";
/* Rights module: initial search message */
"Start a search to edit the rights" = "เริ่มการค้นหาเพื่อแก้ไขสิทธิ์";
/* Rights module: Empty search result */
"No matching user" = "ไม่พบผู้ใช้ที่ตรงกัน";
/* Rights module: no selection */
"No resource selected" = "ไม่ได้เลือกทรัพยากร";
"Add User" = "เพิ่มผู้ใช้";
"Subscribe User" = "สมัครสมาชิกผู้ใช้";
"Rights" = "สิทธิ์";
"Search Users" = "ค้นหาผู้ใช้";
"users found" = "ผู้ใช้พบ";
"No resource" = "ไม่มีทรัพยากร";
"Any Authenticated User" = "ผู้ใช้ที่ได้รับการยืนยันตัวตนใด ๆ";
"Public Access" = "การเข้าถึงสาธารณะ";
"Save" = "บันทึก";
"Clear" = "ชัดเจน";
"Message of the day" = "ข้อความของวันนี้";
"Message of the day has been saved" = "ข้อความของวันนี้ถูกบันทึกแล้ว";
+14 -14
View File
@@ -45,7 +45,7 @@
"Reduce" = "Verminderen";
/* tooltip */
"Refresh" = "Refresh";
"Refresh" = "Vernieuwen";
/* generic.js */
"Unable to subscribe to that folder!"
@@ -109,7 +109,7 @@
"Personal" = "Persoonlijk";
"To Do" = "Te doen";
"Later" = "Later";
"Forwarded" = "Forwarded";
"Forwarded" = "Doorgestuurd";
"Return Receipt Sent" = "Ontvangstbewijs verzonden";
"a2_Sunday" = "Zo";
"a2_Monday" = "Ma";
@@ -122,7 +122,7 @@
"Add User" = "Gebruiker toevoegen";
"Loading" = "Laden";
"No such user." = "Geen dergelijke gebruiker";
"You cannot (un)subscribe to a folder that you own!" = "Kan niet aan- of afmelden van eigen map!";
"You cannot (un)subscribe to a folder that you own!" = "U kunt zich niet (af)melden voor een map waarvan u de eigenaar bent!";
/* SMIME Certificate field */
"S/MIME Certificate" = "S/MIME Certificaat";
@@ -227,16 +227,16 @@
"Move forward" = "Ga vooruit";
/* Password Recovery */
"passwordRecovery_Disabled" = "Disabled";
"passwordRecovery_SecretQuestion" = "Secret question";
"passwordRecovery_SecretQuestion1" = "What is the name of your first pet ?";
"passwordRecovery_SecretQuestion2" = "What was your first car ?";
"passwordRecovery_SecretQuestion3" = "What is your favorite movie ?";
"passwordRecovery_SecondaryEmail" = "Secondary E-mail";
"passwordRecovery_Disabled" = "Uitgezet";
"passwordRecovery_SecretQuestion" = "Geheime vraag";
"passwordRecovery_SecretQuestion1" = "Hoe heet je eerste huisdier?";
"passwordRecovery_SecretQuestion2" = "Wat was je eerste auto?";
"passwordRecovery_SecretQuestion3" = "Wat is je favoriete film?";
"passwordRecovery_SecondaryEmail" = "Secundair e-mailadres";
/* Password */
"POLICY_MIN_LOWERCASE_LETTER" = "Minimum of %{0} lowercase letter";
"POLICY_MIN_UPPERCASE_LETTER" = "Minimum of %{0} uppercase letter";
"POLICY_MIN_DIGIT" = "Minimum of %{0} digit";
"POLICY_MIN_SPECIAL_SYMBOLS" = "Minimum of %{0} special symbols";
"POLICY_MIN_LENGTH" = "Minimum length of %{0} characters";
"POLICY_MIN_LOWERCASE_LETTER" = "Minimaal %{0} kleine letter";
"POLICY_MIN_UPPERCASE_LETTER" = "Minimaal %{0} hoofdletter";
"POLICY_MIN_DIGIT" = "Minimaal %{0} cijfer";
"POLICY_MIN_SPECIAL_SYMBOLS" = "Minimaal %{0} speciale symbolen";
"POLICY_MIN_LENGTH" = "Minimale lengte van %{0} tekens";
+242
View File
@@ -0,0 +1,242 @@
/* this file is in UTF-8 format! */
/* toolbars */
"Save" = "저장";
"Close" = "닫기";
"Edit User Rights" = "사용자 권한 편집";
"Home" = "홈";
"Calendar" = "캘린더";
"Address Book" = "주소록";
"Mail" = "메일";
"Preferences" = "환경설정";
"Administration" = "관리";
"Disconnect" = "연결 끊기";
"Toggle Menu" = "메뉴 전환";
"Right Administration" = "권한 관리";
"Log Console (dev.)" = "로그 콘솔 (개발)";
"User" = "사용자";
"Vacation message is enabled" = "부재중 메시지 활성화됨";
"Help" = "도움말";
"noJavascriptError" = "SOGo를 실행하려면 Javascript가 필요합니다. 브라우저 환경설정에서 이 옵션이 사용 가능하고 활성화되어 있는지 확인하세요.";
"noJavascriptRetry" = "다시 시도";
"Owner" = "소유자";
"Publish the Free/Busy information" = "약속 가능/불가능 정보 게시";
"Add..." = "추가...";
"Remove" = "제거";
"Subscribe User" = "사용자 구독";
"Any Authenticated User" = "모든 인증된 사용자";
"Public Access" = "공개 접근";
"Any user not listed above" = "위에 나열되지 않은 모든 사용자";
"Anybody accessing this resource from the public area" = "공개 영역에서 이 리소스에 접근하는 모든 사람";
"Sorry, the user rights can not be configured for that object." = "죄송합니다, 해당 개체에 대한 사용자 권한은 설정할 수 없습니다.";
"Any user with an account on this system will be able to access your mailbox \"%{0}\". Are you certain you trust them all?"
= "이 시스템에 계정이 있는 모든 사용자가 귀하의 사서함 \"%{0}\"에 접근할 수 있습니다. 그들 모두를 신뢰하십니까?";
"Any user with an account on this system will be able to access your calendar \"%{0}\". Are you certain you trust them all?"
= "이 시스템에 계정이 있는 모든 사용자가 귀하의 캘린더 \"%{0}\"에 접근할 수 있습니다. 그들 모두를 신뢰하십니까?";
"Potentially anyone on the Internet will be able to access your calendar \"%{0}\", even if they do not have an account on this system. Is this information suitable for the public Internet?"
= "이 시스템에 계정이 없더라도 인터넷상의 누구나 귀하의 캘린더 \"%{0}\"에 접근할 수 있습니다. 이 정보는 공개 인터넷에 적합합니까?";
"Any user with an account on this system will be able to access your address book \"%{0}\". Are you certain you trust them all?"
= "이 시스템에 계정이 있는 모든 사용자가 귀하의 주소록 \"%{0}\"에 접근할 수 있습니다. 그들 모두를 신뢰하십니까?";
"Potentially anyone on the Internet will be able to access your address book \"%{0}\", even if they do not have an account on this system. Is this information suitable for the public Internet?"
= "이 시스템에 계정이 없더라도 인터넷상의 누구나 귀하의 주소록 \"%{0}\"에 접근할 수 있습니다. 이 정보는 공개 인터넷에 적합합니까?";
"Give Access" = "접근 권한 부여";
"Keep Private" = "비공개 유지";
"Expand" = "확장";
"Reduce" = "축소";
/* tooltip */
"Refresh" = "새로고침";
/* generic.js */
"Unable to subscribe to that folder!"
= "해당 폴더를 구독할 수 없습니다!";
"You cannot subscribe to a folder that you own!"
= "소유하고 있는 폴더는 구독할 수 없습니다!";
"Unable to unsubscribe from that folder!"
= "해당 폴더 구독을 취소할 수 없습니다!";
"You cannot unsubscribe from a folder that you own!"
= "소유하고 있는 폴더는 구독을 취소할 수 없습니다!";
"Unable to rename that folder!" = "해당 폴더 이름을 바꿀 수 없습니다!";
"You have already subscribed to that folder!"
= "이미 해당 폴더를 구독했습니다!";
"The user rights cannot be edited for this object!"
= "이 개체에 대한 사용자 권한은 편집할 수 없습니다!";
"A folder by that name already exists." = "해당 이름의 폴더가 이미 존재합니다.";
"You cannot create a list in a shared address book."
= "공유 주소록에서는 목록을 생성할 수 없습니다.";
"Warning" = "경고";
"Can't contact server" = "서버와 통신하는 중 오류가 발생했습니다. 나중에 다시 시도해 주세요.";
"You are not allowed to access this module or this system. Please contact your system administrator."
= "이 모듈 또는 이 시스템에 접근할 수 없습니다. 시스템 관리자에게 문의하십시오.";
"You don't have the required privileges to perform the operation."
= "이 작업을 수행하는 데 필요한 권한이 없습니다.";
"noEmailForDelegation" = "초대를 위임할 주소를 지정해야 합니다.";
"delegate is organizer" = "위임자가 주최자입니다. 다른 위임자를 지정하십시오.";
"delegate is a participant" = "위임자가 이미 참가자입니다.";
"delegate is a group" = "지정된 주소는 그룹에 해당합니다. 개별 사용자에게만 위임할 수 있습니다.";
/* common buttons */
"OK" = "확인";
"Cancel" = "취소";
"Yes" = "예";
"No" = "아니요";
/* generic messages */
"Error" = "오류";
"Success" = "성공";
/* confirmation dialog box */
"Confirmation" = "확인";
/* alarms */
"Reminder" = "알림";
"Start" = "시작";
"Due Date" = "마감일";
"Location" = "장소";
"Snooze" = "다시 알림";
"Snooze for " = "다시 알림 ";
"5 minutes" = "5분";
"10 minutes" = "10분";
"15 minutes" = "15분";
"30 minutes" = "30분";
"45 minutes" = "45분";
"1 hour" = "1시간";
"1 day" = "1일";
/* mail labels */
"Important" = "중요";
"Work" = "업무";
"Personal" = "개인";
"To Do" = "할 일";
"Later" = "나중에";
"Forwarded" = "전달됨";
"Return Receipt Sent" = "읽음 확인 전송됨";
"a2_Sunday" = "일";
"a2_Monday" = "월";
"a2_Tuesday" = "화";
"a2_Wednesday" = "수";
"a2_Thursday" = "목";
"a2_Friday" = "금";
"a2_Saturday" = "토";
"Access Rights" = "접근 권한";
"Add User" = "사용자 추가";
"Loading" = "로딩 중";
"No such user." = "해당 사용자가 없습니다.";
"You cannot (un)subscribe to a folder that you own!" = "소유하고 있는 폴더는 (구독/구독 취소)할 수 없습니다!";
/* SMIME Certificate field */
"S/MIME Certificate" = "S/MIME 인증서";
"Subject Name" = "주체 이름";
"Issuer" = "발급자";
"streetAddress" = "거리 주소";
"stateOrProvinceName" = "주 또는 시/도";
"localityName" = "지역";
"countryName" = "국가";
"organizationName" = "기관명";
"organizationalUnitName" = "조직 단위";
"commonName" = "일반 이름";
"surname" = "성";
"givenName" = "이름";
"emailAddress" = "이메일 주소";
/* Authentication username */
"Username" = "사용자명";
/* Authentication password */
"Password" = "비밀번호";
/* Authentication failed */
"Wrong username or password." = "잘못된 사용자명 또는 비밀번호입니다.";
/* Error message displayed bellow search field when the search string has less than the required number of characters */
"Enter at least %{minimumSearchLength} characters" = "최소 %{minimumSearchLength}자를 입력하세요";
/* Error message displayed when a file upload exceeds WOMaxUploadSize */
"File size upload limit reached" = "파일 크기 업로드 제한에 도달했습니다";
/* Generic server error */
"An error occured, please try again." = "An error occured, please try again.";
/* Open datepicker */
"Open Calendar" = "캘린더 열기";
/* Toggle visibility (ex: mail account in left navigation menu) */
"Toggle visibility" = "가시성 전환";
"Keyboard Shortcuts" = "키보드 단축키";
/* Aria label for avatar button to select and unselect an item */
"Toggle item" = "항목 전환";
/* Toggle multiple items at the same time (hotkeys cheatsheet) */
"Toggle range of items" = "항목 범위 전환";
/* Question mark shows list of hotkeys */
"Show or hide this help" = "이 도움말 표시 또는 숨기기";
/* Space key */
"key_space" = "스페이스";
/* Delete key */
"key_delete" = "삭제";
/* Shift and space key */
"key_shift+space" = "시프트 + 스페이스";
/* Up arrow key */
"key_up" = "↑";
/* Down arrow key */
"key_down" = "↓";
/* Left arrow key */
"key_left" = "←";
/* Right arrow key */
"key_right" = "→";
/* Shift and up arrow combo keys */
"key_shift+up" = "시프트 + ↑";
/* Shift and down arrow combo keys */
"key_shift+down" = "시프트 + ↓";
/* Backspace key */
"key_backspace" = "⌫";
/* Hotkey to start a search */
"hotkey_search" = "s";
/* Hotkey description to select next list item */
"View next item" = "다음 항목 보기";
/* Hotkey description to select previous list item */
"View previous item" = "이전 항목 보기";
/* Hotkey description to add next list item to selection */
"Add next item to selection" = "선택 항목에 다음 항목 추가";
/* Hotkey description to add previous list item to selection */
"Add previous item to selection" = "선택 항목에 이전 항목 추가";
/* Hotkey description to move backward in current view */
"Move backward" = "뒤로 이동";
/* Hotkey description to move forward in current view */
"Move forward" = "앞으로 이동";
/* Password Recovery */
"passwordRecovery_Disabled" = "비활성화됨";
"passwordRecovery_SecretQuestion" = "비밀 질문";
"passwordRecovery_SecretQuestion1" = "첫 번째 반려동물의 이름은 무엇인가요?";
"passwordRecovery_SecretQuestion2" = "첫 번째 자동차는 무엇이었나요?";
"passwordRecovery_SecretQuestion3" = "가장 좋아하는 영화는 무엇인가요?";
"passwordRecovery_SecondaryEmail" = "보조 이메일";
/* Password */
"POLICY_MIN_LOWERCASE_LETTER" = "최소 %{0}개의 소문자";
"POLICY_MIN_UPPERCASE_LETTER" = "최소 %{0}개의 대문자";
"POLICY_MIN_DIGIT" = "최소 %{0}개의 숫자";
"POLICY_MIN_SPECIAL_SYMBOLS" = "최소 %{0}개의 특수 기호";
"POLICY_MIN_LENGTH" = "최소 길이 %{0}자";
+242
View File
@@ -0,0 +1,242 @@
/* this file is in UTF-8 format! */
/* toolbars */
"Save" = "บันทึก";
"Close" = "ปิด";
"Edit User Rights" = "แก้ไขสิทธิผู้ใช้";
"Home" = "บ้าน";
"Calendar" = "ปฏิทิน";
"Address Book" = "สมุดที่อยู่";
"Mail" = "จดหมาย";
"Preferences" = "การตั้งค่าที่ต้องการ";
"Administration" = "การบริหาร";
"Disconnect" = "ตัดการเชื่อมต่อ";
"Toggle Menu" = "เปิด/ปิดเมนู";
"Right Administration" = "การบริหารจัดการสิทธิ์";
"Log Console (dev.)" = "คอนโซลบันทึก (dev.)";
"User" = "ผู้ใช้";
"Vacation message is enabled" = "ข้อความการพักผ่อนถูกเปิดใช้งาน";
"Help" = "ช่วยเหลือ";
"noJavascriptError" = "SOGo ต้องการ Javascript เพื่อให้ทำงาน โปรดตรวจสอบและเปิดใช้งานตัวเลือกนี้ภายในการตั้งค่าเบราว์เซอร์ของคุณ";
"noJavascriptRetry" = "ลองใหม่";
"Owner" = "เจ้าของ";
"Publish the Free/Busy information" = "เผยแพร่ข้อมูลว่างเสรี/ไม่ว่างเสรี";
"Add..." = "เพิ่ม...";
"Remove" = "ลบ";
"Subscribe User" = "สมัครสมาชิกผู้ใช้";
"Any Authenticated User" = "ผู้ใช้ที่ได้รับการยืนยันตัวตนใด ๆ";
"Public Access" = "การเข้าถึงสาธารณะ";
"Any user not listed above" = "ผู้ใช้ที่ไม่ได้ระบุไว้ในรายชื่อด้านบน";
"Anybody accessing this resource from the public area" = "ใครก็ตามที่เข้าถึงทรัพยากรนี้จากพื้นที่สาธารณะ";
"Sorry, the user rights can not be configured for that object." = "ขอโทษครับ ไม่สามารถกำหนดสิทธิ์ผู้ใช้สำหรับวัตถุดังกล่าวได้";
"Any user with an account on this system will be able to access your mailbox \"%{0}\". Are you certain you trust them all?"
= "ใครก็ตามที่มีบัญชีบนระบบนี้จะสามารถเข้าถึงกล่องจดหมายของคุณ \"%{0}\" ได้ คุณแน่ใจหรือว่าคุณไว้ใจพวกเขาทั้งหมด?";
"Any user with an account on this system will be able to access your calendar \"%{0}\". Are you certain you trust them all?"
= "ใครก็ตามที่มีบัญชีบนระบบนี้จะสามารถเข้าถึงปฏิทินของคุณ \"%{0}\" ได้ คุณแน่ใจหรือว่าคุณไว้ใจพวกเขาทั้งหมด?";
"Potentially anyone on the Internet will be able to access your calendar \"%{0}\", even if they do not have an account on this system. Is this information suitable for the public Internet?"
= "ใครก็ตามบนอินเทอร์เน็ตอาจสามารถเข้าถึงปฏิทินของคุณ \"%{0}\" ได้ แม้ว่าพวกเขาจะไม่มีบัญชีในระบบนี้เลย ข้อมูลนี้เหมาะสำหรับอินเทอร์เน็ตสาธารณะหรือไม่?";
"Any user with an account on this system will be able to access your address book \"%{0}\". Are you certain you trust them all?"
= "ใครก็ตามที่มีบัญชีบนระบบนี้จะสามารถเข้าถึงสมุดที่อยู่ของคุณ \"%{0}\" ได้ คุณแน่ใจหรือว่าคุณไว้ใจพวกเขาทั้งหมด?";
"Potentially anyone on the Internet will be able to access your address book \"%{0}\", even if they do not have an account on this system. Is this information suitable for the public Internet?"
= "ใครก็ตามบนอินเทอร์เน็ตอาจสามารถเข้าถึงสมุดที่อยู่ของคุณ \"%{0}\" ได้ แม้ว่าพวกเขาจะไม่มีบัญชีในระบบนี้เลย ข้อมูลนี้เหมาะสำหรับอินเทอร์เน็ตสาธารณะหรือไม่?";
"Give Access" = "ให้สิทธิ์เข้าถึง";
"Keep Private" = "เก็บเป็นความลับ";
"Expand" = "ขยาย";
"Reduce" = "ลดลง";
/* tooltip */
"Refresh" = "รีเฟรช";
/* generic.js */
"Unable to subscribe to that folder!"
= "ไม่สามารถสมัครสมาชิกในโฟลเดอร์นั้นได้!";
"You cannot subscribe to a folder that you own!"
= "คุณไม่สามารถสมัครสมาชิกในโฟลเดอร์ที่คุณเป็นเจ้าของ!";
"Unable to unsubscribe from that folder!"
= "ไม่สามารถยกเลิกการสมัครสมาชิกจากโฟลเดอร์นั้นได้!";
"You cannot unsubscribe from a folder that you own!"
= "คุณไม่สามารถยกเลิกการสมัครสมาชิกในโฟลเดอร์ที่คุณเป็นเจ้าของ!";
"Unable to rename that folder!" = "ไม่สามารถเปลี่ยนชื่อโฟลเดอร์นั้นได้!";
"You have already subscribed to that folder!"
= "คุณได้สมัครสมาชิกในโฟลเดอร์นั้นแล้ว!";
"The user rights cannot be edited for this object!"
= "ไม่สามารถแก้ไขสิทธิ์ของผู้ใช้สำหรับวัตถุนี้ได้!";
"A folder by that name already exists." = "มีโฟลเดอร์ด้วยชื่อนั้นอยู่แล้ว";
"You cannot create a list in a shared address book."
= "คุณไม่สามารถสร้างรายการในสมุดที่อยู่ร่วมกันได้";
"Warning" = "คำเตือน";
"Can't contact server" = "เกิดข้อผิดพลาดขึ้นในขณะที่ติดต่อกับเซิร์ฟเวอร์ โปรดลองอีกครั้งในภายหลัง";
"You are not allowed to access this module or this system. Please contact your system administrator."
= "คุณไม่ได้รับอนุญาตให้เข้าถึงโมดูลหรือระบบนี้ โปรดติดต่อผู้ดูแลระบบของคุณ";
"You don't have the required privileges to perform the operation."
= "คุณไม่มีสิทธิ์ที่จำเป็นในการดำเนินการ";
"noEmailForDelegation" = "คุณต้องระบุที่อยู่ที่คุณต้องการมอบหมายให้กับคำเชิญของคุณ";
"delegate is organizer" = "ผู้แทนเป็นผู้จัดงาน โปรดระบุผู้แทนอื่น";
"delegate is a participant" = "ผู้แทนถูกเข้าร่วมอยู่แล้ว.";
"delegate is a group" = "ที่อยู่ที่ระบุตรงกับกลุ่ม คุณสามารถมอบหมายให้กับบุคคลที่เป็นเอกลักษณ์เท่านั้น";
/* common buttons */
"OK" = "ตกลง";
"Cancel" = "ยกเลิก";
"Yes" = "ใช่";
"No" = "ไม่";
/* generic messages */
"Error" = "ข้อผิดพลาด";
"Success" = "สำเร็จ";
/* confirmation dialog box */
"Confirmation" = "ยืนยัน";
/* alarms */
"Reminder" = "เตือนความจำ";
"Start" = "เริ่ม";
"Due Date" = "วันครบกำหนด";
"Location" = "สถานที่";
"Snooze" = "หลับตา";
"Snooze for " = "Snooze for";
"5 minutes" = "5 นาที";
"10 minutes" = "10 นาที";
"15 minutes" = "15 นาที";
"30 minutes" = "30 นาที";
"45 minutes" = "45 นาที";
"1 hour" = "1 ชั่วโมง";
"1 day" = "1 วัน";
/* mail labels */
"Important" = "สำคัญ";
"Work" = "งาน";
"Personal" = "ส่วนตัว";
"To Do" = "ทำ";
"Later" = "หลังจากนั้น";
"Forwarded" = "ส่งต่อ";
"Return Receipt Sent" = "ใบตอบรับการส่งได้รับแล้ว";
"a2_Sunday" = "อา";
"a2_Monday" = "จ";
"a2_Tuesday" = "อ";
"a2_Wednesday" = "พ";
"a2_Thursday" = "พฤ";
"a2_Friday" = "ศ";
"a2_Saturday" = "ส";
"Access Rights" = "สิทธิ์การเข้าถึง";
"Add User" = "เพิ่มผู้ใช้";
"Loading" = "โหลด";
"No such user." = "ไม่มีผู้ใช้งานดังกล่าว";
"You cannot (un)subscribe to a folder that you own!" = "คุณไม่สามารถสมัครสมาชิกในโฟลเดอร์ที่คุณเป็นเจ้าของ!";
/* SMIME Certificate field */
"S/MIME Certificate" = "ใบรับรอง S/MIME";
"Subject Name" = "ชื่อเรื่อง";
"Issuer" = "ผู้ออก";
"streetAddress" = "ถนน";
"stateOrProvinceName" = "รัฐหรือจังหวัด";
"localityName" = "สถานที่";
"countryName" = "ประเทศ";
"organizationName" = "องค์กร";
"organizationalUnitName" = "หน่วยงานองค์กร";
"commonName" = "ชื่อทั่วไป";
"surname" = "นามสกุล";
"givenName" = "ชื่อจริง";
"emailAddress" = "ที่อยู่อีเมล์";
/* Authentication username */
"Username" = "ชื่อผู้ใช้";
/* Authentication password */
"Password" = "รหัสผ่าน";
/* Authentication failed */
"Wrong username or password." = "ชื่อผู้ใช้หรือรหัสผ่านไม่ถูกต้อง.";
/* Error message displayed bellow search field when the search string has less than the required number of characters */
"Enter at least %{minimumSearchLength} characters" = "ป้อนอย่างน้อย %{minimumSearchLength} ตัวอักษร";
/* Error message displayed when a file upload exceeds WOMaxUploadSize */
"File size upload limit reached" = "ขนาดไฟล์ที่อัปโหลดเกินขีดจำกัด";
/* Generic server error */
"An error occured, please try again." = "เกิดข้อผิดพลาด โปรดลองอีกครั้ง";
/* Open datepicker */
"Open Calendar" = "เปิดปฏิทิน";
/* Toggle visibility (ex: mail account in left navigation menu) */
"Toggle visibility" = "เปลี่ยนการมองเห็น";
"Keyboard Shortcuts" = "แป้นพิมพ์ลัด";
/* Aria label for avatar button to select and unselect an item */
"Toggle item" = "เปิด-ปิดรายการ";
/* Toggle multiple items at the same time (hotkeys cheatsheet) */
"Toggle range of items" = "เปลี่ยนสถานะของรายการ";
/* Question mark shows list of hotkeys */
"Show or hide this help" = "แสดงหรือซ่อนความช่วยเหลือนี้";
/* Space key */
"key_space" = "พื้นที่";
/* Delete key */
"key_delete" = "ลบ";
/* Shift and space key */
"key_shift+space" = "shift + space";
/* Up arrow key */
"key_up" = "↑";
/* Down arrow key */
"key_down" = "↓";
/* Left arrow key */
"key_left" = "←";
/* Right arrow key */
"key_right" = "→";
/* Shift and up arrow combo keys */
"key_shift+up" = "shift + ↑";
/* Shift and down arrow combo keys */
"key_shift+down" = "shift + ↓";
/* Backspace key */
"key_backspace" = "⌫";
/* Hotkey to start a search */
"hotkey_search" = "s";
/* Hotkey description to select next list item */
"View next item" = "ดูรายการถัดไป";
/* Hotkey description to select previous list item */
"View previous item" = "ดูรายการก่อนหน้า";
/* Hotkey description to add next list item to selection */
"Add next item to selection" = "เพิ่มรายการถัดไปในการเลือก";
/* Hotkey description to add previous list item to selection */
"Add previous item to selection" = "เพิ่มรายการก่อนหน้านี้ในการเลือก";
/* Hotkey description to move backward in current view */
"Move backward" = "ย้ายถอยหลัง";
/* Hotkey description to move forward in current view */
"Move forward" = "เคลื่อนไปข้างหน้า";
/* Password Recovery */
"passwordRecovery_Disabled" = "ปิดการใช้งาน";
"passwordRecovery_SecretQuestion" = "คำถามลับ";
"passwordRecovery_SecretQuestion1" = "ชื่อสัตว์เลี้ยงครั้งแรกของคุณคืออะไร?";
"passwordRecovery_SecretQuestion2" = "คุณมีรถคันแรกของคุณอยู่ที่ไหน?";
"passwordRecovery_SecretQuestion3" = "หนังเรื่องไหนเป็นหนังที่คุณชื่นชอบ?";
"passwordRecovery_SecondaryEmail" = "อีเมลสำรอง";
/* Password */
"POLICY_MIN_LOWERCASE_LETTER" = "อักษรตัวพิมพ์เล็กขั้นต่ำ %{0} ตัว";
"POLICY_MIN_UPPERCASE_LETTER" = "อักษรตัวตัวพิมพ์ใหญ่ขั้นต่ำ %{0} ตัว";
"POLICY_MIN_DIGIT" = "ตัวเลขขั้นต่ำ %{0} หลัก";
"POLICY_MIN_SPECIAL_SYMBOLS" = "สัญลักษณ์พิเศษขั้นต่ำ %{0} ตัว";
"POLICY_MIN_LENGTH" = "ความยาวขั้นต่ำ %{0} ตัว";
@@ -235,8 +235,8 @@
"passwordRecovery_SecondaryEmail" = "İkincil e-posta";
/* Password */
"POLICY_MIN_LOWERCASE_LETTER" = "Minimum of %{0} lowercase letter";
"POLICY_MIN_UPPERCASE_LETTER" = "Minimum of %{0} uppercase letter";
"POLICY_MIN_DIGIT" = "Minimum of %{0} digit";
"POLICY_MIN_SPECIAL_SYMBOLS" = "Minimum of %{0} special symbols";
"POLICY_MIN_LENGTH" = "Minimum length of %{0} characters";
"POLICY_MIN_LOWERCASE_LETTER" = "En az %{0} küçük harf";
"POLICY_MIN_UPPERCASE_LETTER" = "En az %{0} büyük harf";
"POLICY_MIN_DIGIT" = "En az %{0} rakam";
"POLICY_MIN_SPECIAL_SYMBOLS" = "En az %{0} özel simge";
"POLICY_MIN_LENGTH" = "En az %{0} karakter uzunluğunda";
+1 -1
View File
@@ -193,7 +193,7 @@
"Work" = "Werk";
"Mobile" = "Mobiel";
"Pager" = "Pieper";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuration profile";
"Download iOS - MacOS configuration profile" = "Download iOS - MacOS configuratieprofiel";
/* categories */
"contacts_category_labels" = "Collega, Concurrent, Klant, Vriend, Familie, Zakenpartner, Leverancier, Pers, VIP";
@@ -0,0 +1,366 @@
/* this file is in UTF-8 format! */
"Contact" = "연락처";
"Address" = "주소";
"Photos" = "사진";
"Other" = "기타";
"Address Books" = "주소록";
"Addressbook" = "주소록";
"Addresses" = "주소";
"Update" = "업데이트";
"Cancel" = "취소";
"Common" = "공통";
"Contact editor" = "연락처 편집기";
"Contact viewer" = "연락처 뷰어";
"Email" = "이메일";
"Screen Name" = "스크린 이름";
"Extended" = "확장";
"Fax" = "팩스";
"Firstname" = "이름";
"Home" = "집";
"HomePhone" = "집 전화";
"Lastname" = "성";
"Location" = "위치";
"Add a category" = "카테고리 추가";
"MobilePhone" = "휴대폰";
"Name" = "이름";
"OfficePhone" = "회사 전화";
"Organization" = "기관";
"Work Phone" = "직장 전화";
"Cell" = "휴대폰";
"Pager" = "호출기";
"Pref" = "기본";
"Phone" = "전화";
"Phones" = "전화번호";
"Postal" = "우편";
"Save" = "저장";
"Internet" = "인터넷";
"Unit" = "단위";
"delete" = "삭제";
"edit" = "편집";
"invalidemailwarn" = "지정된 이메일이 유효하지 않습니다";
"new" = "새로 만들기";
"Preferred Phone" = "기본 전화번호";
"Move To" = "이동";
"Copy To" = "복사";
"Add to" = "추가";
"To" = "받는 사람";
"Carbon Copy (Cc)" = "참조 (Cc)";
"Blind Carbon Copy (Bcc)" = "숨은 참조 (Bcc)";
/* Search scope: name fields */
"name" = "이름";
/* Search scope: name fields */
"c_cn" = "이름";
/* Search scope: secondary email field */
"mozillanickname" = "보조 이메일";
/* Search scope: screen name field */
"nsaimid" = "스크린 이름";
/* Search scope: mail fields */
"mail" = "메일";
/* Search scope: mail fields */
"c_mail" = "메일";
/* Search scope: telephone field */
"telephonenumber" = "전화";
/* Search scope: telephone field */
"homephone" = "전화";
/* Search scope: mobile field */
"mobile" = "모바일";
/* Search scope: fax field */
"facsimiletelephonenumber" = "팩스";
/* Search scope: pager field */
"pager" = "호출기";
/* Search scope: categories field */
"c_categories" = "카테고리";
/* Search scope: categories field */
"vcardcategories" = "카테고리";
/* Search scope: title field */
"title" = "직함";
/* Search scope: organization field */
"c_o" = "기관";
/* Search scope: organization field */
"o" = "기관";
/* Search scope: department field */
"ou" = "부서";
/* Search scope: city field */
"l" = "도시";
/* Search scope: country field */
"c" = "국가";
/* Search scope: home address field */
"mozillahomestreet" = "집 주소";
/* Search scope: state/province field */
"st" = "주/도";
/* Search scope: home state/province field */
"mozillahomestate" = "집 주/도";
/* Search scope: zip/postal code field */
"postalCode" = "우편/우편번호";
/* Search scope: home zip/postal code field */
"mozillahomepostalcode" = "우편/우편번호";
/* Search scope: home country field */
"mozillahomecountryname" = "집 국가";
/* Search scope: home web page field */
"mozillahomeurl" = "홈페이지";
/* Search scope: work web page field */
"mozillaworkurl" = "웹 페이지";
/* Search scope: note field */
"description" = "메모";
/* Subheader of empty addressbook */
"No contact" = "연락처 없음";
/* Subheader of system addressbook */
"Start a search to browse this address book" = "이 주소록을 탐색하려면 검색을 시작하십시오";
/* Number of contacts in addressbook; string is prefixed by number */
"contacts" = "연락처";
/* No contact matching search criteria */
"No matching contact" = "일치하는 연락처 없음";
/* Number of contacts matching search criteria; string is prefixed by number */
"matching contacts" = "일치하는 연락처";
/* Number of selected contacts in list */
"selected" = "선택됨";
/* Empty right pane */
"No contact selected" = "선택된 연락처 없음";
/* Tooltips */
"Create a new address book card" = "새 주소록 카드 만들기";
"Create a new list" = "새 목록 만들기";
"Edit the selected card" = "선택한 카드 편집";
"Send a mail message" = "메일 메시지 보내기";
"Delete selected card or address book" = "선택한 카드 또는 주소록 삭제";
"Reload all contacts" = "모든 연락처 새로고침";
"htmlMailFormat_UNKNOWN" = "알 수 없음";
"htmlMailFormat_FALSE" = "일반 텍스트";
"htmlMailFormat_TRUE" = "HTML";
"Name or Email" = "이름 또는 이메일";
"Category" = "카테고리";
"Personal Addressbook" = "개인 주소록";
"Search in Addressbook" = "주소록 검색";
"New Card" = "새 카드";
"New List" = "새 목록";
"Edit" = "편집";
"Properties" = "속성";
"Sharing..." = "공유...";
"Write" = "쓰기";
"Delete" = "삭제";
"Instant Message" = "인스턴트 메시지";
"Add..." = "추가...";
"Remove" = "제거";
"Please wait..." = "기다려 주십시오...";
"No possible subscription" = "구독할 수 없음";
"Preferred" = "기본";
"Display" = "표시";
"Display Name" = "표시 이름";
"Additional Email" = "추가 이메일";
"Phone Number" = "전화번호";
"Prefers to receive messages formatted as" = "선호하는 메시지 형식";
"Categories" = "카테고리";
"First" = "이름";
"Last" = "성";
"Nickname" = "별명";
"Telephone" = "전화";
"Work" = "직장";
"Mobile" = "휴대폰";
"Pager" = "호출기";
"Download iOS - MacOS configuration profile" = "iOS - MacOS 구성 프로필 다운로드";
/* categories */
"contacts_category_labels" = "동료, 경쟁사, 고객, 친구, 가족, 비즈니스 파트너, 공급업체, 언론, VIP";
"New category" = "새 카테고리";
/* adresses */
"Title" = "직함";
"Service" = "서비스";
"Company" = "회사";
"Department" = "부서";
"City" = "도시";
"State_Province" = "주/도";
"ZIP_Postal Code" = "우편/우편번호";
"Country" = "국가";
"Web Page" = "웹 페이지";
"Other Infos" = "기타 정보";
"Note" = "메모";
"Timezone" = "시간대";
"Birthday" = "생일";
"Birthday (yyyy-mm-dd)" = "생일 (yyyy-mm-dd)";
"Freebusy URL" = "약속 가능/불가능 URL";
"Add as..." = "다음으로 추가...";
"Recipient" = "받는 사람";
"Carbon Copy" = "참조";
"Blind Carbon Copy" = "숨은 참조";
"New Addressbook..." = "새 주소록...";
"Subscribe to an Addressbook..." = "주소록 구독...";
"Remove the selected Addressbook" = "선택한 주소록 제거";
"Subscribe to a shared contact" = "공유 주소록 구독";
"Search User" = "사용자 검색";
"Name of the Address Book" = "주소록 이름";
"Are you sure you want to delete the selected address book?"
= "선택한 주소록을 삭제하시겠습니까?";
"Are you sure you want to delete the addressbook \"%{0}\"?"
= "주소록 \"%{0}\"을 삭제하시겠습니까?";
"You cannot remove nor unsubscribe from a public addressbook."
= "공개 주소록은 제거하거나 구독 취소할 수 없습니다.";
"You cannot remove nor unsubscribe from your personal addressbook."
= "개인 주소록은 제거하거나 구독 취소할 수 없습니다.";
"Are you sure you want to delete the selected contacts?"
= "선택한 연락처를 삭제하시겠습니까?";
"Are you sure you want to delete the card of %{0}?" = "%{0}의 카드를 삭제하시겠습니까?";
"You cannot delete the card of \"%{0}\"."
= "\"%{0}\"의 카드를 삭제할 수 없습니다.";
"You cannot subscribe to a folder that you own!"
= "소유하고 있는 폴더는 구독할 수 없습니다.";
"Unable to subscribe to that folder!"
= "해당 폴더를 구독할 수 없습니다.";
/* security */
"Security" = "보안";
"Uninstall" = "제거";
"Error reading the card certificate." = "카드 인증서 읽기 오류.";
"No certificate associated to card." = "카드와 연결된 인증서가 없습니다.";
/* acls */
"Access rights to" = "접근 권한 대상";
"For user" = "사용자";
"Any Authenticated User" = "모든 인증된 사용자";
"Public Access" = "공개 접근";
"This person can add cards to this addressbook."
= "이 사람은 이 주소록에 카드를 추가할 수 있습니다.";
"This person can edit the cards of this addressbook."
= "이 사람은 이 주소록의 카드를 편집할 수 있습니다.";
"This person can list the content of this addressbook."
= "이 사람은 이 주소록의 내용을 나열할 수 있습니다.";
"This person can read the cards of this addressbook."
= "이 사람은 이 주소록의 카드를 읽을 수 있습니다.";
"This person can erase cards from this addressbook."
= "이 사람은 이 주소록에서 카드를 지울 수 있습니다.";
"The selected contact has no email address."
= "선택한 연락처에 이메일 주소가 없습니다.";
"Please select a contact." = "연락처를 선택하십시오.";
/* Messages for move and copy */
"%{0} card(s) copied" = "%{0}개 카드 복사됨";
"%{0} card(s) moved" = "%{0}개 카드 이동됨";
"SoAccessDeniedException" = "이 주소록에 쓸 수 없습니다.";
"Forbidden" = "금지됨";
"Invalid Contact" = "선택한 연락처가 더 이상 존재하지 않습니다.";
"Unknown Destination Folder" = "선택한 대상 주소록이 더 이상 존재하지 않습니다.";
/* Lists */
"List details" = "목록 세부 정보";
"List name" = "목록 이름";
"List nickname" = "목록 별명";
"List description" = "목록 설명";
"Members" = "회원";
"Contacts" = "연락처";
"Add" = "추가";
"Lists can't be moved or copied." = "목록은 이동하거나 복사할 수 없습니다.";
"Export" = "내보내기";
"Export Address Book..." = "주소록 내보내기...";
"View Raw Source" = "원본 내용 보기";
/* Import */
"Import Cards" = "카드 가져오기";
"Select a vCard or LDIF file." = "vCard 또는 LDIF 파일을 선택하십시오.";
"Upload" = "업로드";
"Uploading" = "업로드 중";
"Done" = "완료";
"An error occured while importing contacts." = "연락처 가져오기 중 오류가 발생했습니다.";
"No card was imported." = "가져온 카드가 없습니다.";
"A total of %{0} cards were imported in the addressbook." = "총 %{0}개의 카드가 주소록으로 가져와졌습니다.";
"Reload" = "새로고침";
/* Properties window */
"Address Book Name" = "주소록 이름";
"Links to this Address Book" = "이 주소록 링크";
"Authenticated User Access" = "인증된 사용자 접근";
"CardDAV URL" = "CardDAV URL";
"Options" = "옵션";
"Rename" = "이름 변경";
"Subscriptions" = "구독";
"Global Addressbooks" = "전역 주소록";
"Search" = "검색";
"Sort" = "정렬";
"Descending Order" = "내림차순";
"Back" = "뒤로";
"Select All" = "모두 선택";
"Copy contacts" = "연락처 복사";
"More messages options" = "더 많은 메시지 옵션";
"New Contact" = "새 연락처";
"Close" = "닫기";
"More contact options" = "더 많은 연락처 옵션";
"Organization Unit" = "조직 단위";
"Add Organizational Unit" = "조직 단위 추가";
"Type" = "유형";
"Email Address" = "이메일 주소";
"New Email Address" = "새 이메일 주소";
"New Phone Number" = "새 전화번호";
"URL" = "URL";
"New URL" = "새 URL";
"street" = "거리";
"street (continued)" = "거리 (계속)";
"Postoffice" = "우체국";
"Region" = "지역";
"Postal Code" = "우편번호";
"New Address" = "새 주소";
"Reset" = "재설정";
"Description" = "설명";
"Add Member" = "멤버 추가";
"Subscribe" = "구독";
"Add Birthday" = "생일 추가";
"Import" = "가져오기";
"More options" = "더 많은 옵션";
"Role" = "역할";
"Add Screen Name" = "스크린 이름 추가";
"Custom 1" = "사용자 지정 1";
"Custom 2" = "사용자 지정 2";
"Custom 3" = "사용자 지정 3";
"Custom 4" = "사용자 지정 4";
"Custom Value" = "사용자 지정 값";
"New Custom Value" = "새 사용자 지정 값";
"Synchronization" = "동기화";
"Synchronize" = "동기화";
"Sucessfully subscribed to address book" = "주소록 구독 성공";
"A similar card already exists. Would you like to save it anyway?" = "유사한 카드가 이미 존재합니다. 그래도 저장하시겠습니까?";
/* Aria label for scope of search on contacts */
"Search scope" = "검색 범위";
/* Aria label for avatar button to select and unselect a card */
"Toggle item" = "항목 전환";
/* Hotkey to create a new card */
"key_create_card" = "c";
/* Hotkey to create a new list */
"key_create_list" = "l";
+366
View File
@@ -0,0 +1,366 @@
/* this file is in UTF-8 format! */
"Contact" = "ผู้ติดต่อ";
"Address" = "ที่อยู่";
"Photos" = "รูปภาพ";
"Other" = "อื่นๆ";
"Address Books" = "สมุดรายชื่อ";
"Addressbook" = "สมุดที่อยู่";
"Addresses" = "ที่อยู่";
"Update" = "อัปเดต";
"Cancel" = "ยกเลิก";
"Common" = "ทั่วไป";
"Contact editor" = "ติดต่อบรรณาธิการ";
"Contact viewer" = "ผู้ดูแลรายชื่อติดต่อ";
"Email" = "อีเมล";
"Screen Name" = "ชื่อหน้าจอ";
"Extended" = "ขยายออก";
"Fax" = "แฟกซ์";
"Firstname" = "ชื่อจริง";
"Home" = "บ้าน";
"HomePhone" = "โทรศัพท์บ้าน";
"Lastname" = "นามสกุล";
"Location" = "สถานที่";
"Add a category" = "เพิ่มหมวดหมู่";
"MobilePhone" = "โทรศัพท์มือถือ";
"Name" = "ชื่อ";
"OfficePhone" = "โทรศัพท์ในสำนักงาน";
"Organization" = "องค์กร";
"Work Phone" = "โทรศัพท์ที่ใช้ในการทำงาน";
"Cell" = "เซลล์";
"Pager" = "เพจเจอร์";
"Pref" = "การตั้งค่า";
"Phone" = "โทรศัพท์";
"Phones" = "โทรศัพท์";
"Postal" = "ไปรษณีย์";
"Save" = "บันทึก";
"Internet" = "อินเทอร์เน็ต";
"Unit" = "หน่วย";
"delete" = "ลบ";
"edit" = "แก้ไข";
"invalidemailwarn" = "ระบุอีเมลที่ระบุไม่ถูกต้อง";
"new" = "ใหม่";
"Preferred Phone" = "โทรศัพท์ที่ต้องการ";
"Move To" = "ย้ายไป";
"Copy To" = "คัดลอกไปยัง";
"Add to" = "เพิ่มเข้าไป";
"To" = "ถึง";
"Carbon Copy (Cc)" = "คัดลอกคาร์บอน (Cc)";
"Blind Carbon Copy (Bcc)" = "สำเนาบนซองที่มองไม่เห็น (Bcc)";
/* Search scope: name fields */
"name" = "ชื่อ";
/* Search scope: name fields */
"c_cn" = "ชื่อ";
/* Search scope: secondary email field */
"mozillanickname" = "อีเมลสำรอง";
/* Search scope: screen name field */
"nsaimid" = "ชื่อหน้าจอ";
/* Search scope: mail fields */
"mail" = "อีเมล";
/* Search scope: mail fields */
"c_mail" = "อีเมล";
/* Search scope: telephone field */
"telephonenumber" = "โทรศัพท์";
/* Search scope: telephone field */
"homephone" = "โทรศัพท์";
/* Search scope: mobile field */
"mobile" = "มือถือ";
/* Search scope: fax field */
"facsimiletelephonenumber" = "แฟกซ์";
/* Search scope: pager field */
"pager" = "เพจเจอร์";
/* Search scope: categories field */
"c_categories" = "หมวดหมู่";
/* Search scope: categories field */
"vcardcategories" = "หมวดหมู่";
/* Search scope: title field */
"title" = "หัวข้อ";
/* Search scope: organization field */
"c_o" = "องค์กร";
/* Search scope: organization field */
"o" = "องค์กร";
/* Search scope: department field */
"ou" = "แผนก";
/* Search scope: city field */
"l" = "เมือง";
/* Search scope: country field */
"c" = "ประเทศ";
/* Search scope: home address field */
"mozillahomestreet" = "ที่อยู่บ้าน";
/* Search scope: state/province field */
"st" = "รัฐ/จังหวัด";
/* Search scope: home state/province field */
"mozillahomestate" = "รัฐ/จังหวัดบ้าน";
/* Search scope: zip/postal code field */
"postalCode" = "รหัสไปรษณีย์";
/* Search scope: home zip/postal code field */
"mozillahomepostalcode" = "รหัสไปรษณีย์";
/* Search scope: home country field */
"mozillahomecountryname" = "ประเทศบ้าน";
/* Search scope: home web page field */
"mozillahomeurl" = "หน้าหลัก";
/* Search scope: work web page field */
"mozillaworkurl" = "หน้าเว็บ";
/* Search scope: note field */
"description" = "หมายเหตุ";
/* Subheader of empty addressbook */
"No contact" = "ไม่มีการติดต่อ";
/* Subheader of system addressbook */
"Start a search to browse this address book" = "เริ่มการค้นหาเพื่อเรียกดูสมุดที่อยู่นี้";
/* Number of contacts in addressbook; string is prefixed by number */
"contacts" = "ผู้ติดต่อ";
/* No contact matching search criteria */
"No matching contact" = "ไม่พบผู้ติดต่อที่ตรงกัน";
/* Number of contacts matching search criteria; string is prefixed by number */
"matching contacts" = "การจับคู่ผู้ติดต่อ";
/* Number of selected contacts in list */
"selected" = "เลือก";
/* Empty right pane */
"No contact selected" = "ไม่มีการเลือกติดต่อ";
/* Tooltips */
"Create a new address book card" = "สร้างบัตรสมุดที่อยู่ใหม่";
"Create a new list" = "สร้างรายการใหม่";
"Edit the selected card" = "แก้ไขการ์ดที่เลือก";
"Send a mail message" = "ส่งข้อความอีเมล์";
"Delete selected card or address book" = "ลบบัตรหรือสมุดที่อยู่ที่เลือก";
"Reload all contacts" = "โหลดข้อมูลทั้งหมดใหม่";
"htmlMailFormat_UNKNOWN" = "ไม่ทราบ";
"htmlMailFormat_FALSE" = "ข้อความธรรมดา";
"htmlMailFormat_TRUE" = "HTML";
"Name or Email" = "ชื่อหรืออีเมล์";
"Category" = "หมวดหมู่";
"Personal Addressbook" = "สมุดที่อยู่ส่วนตัว";
"Search in Addressbook" = "ค้นหาในสมุดที่อยู่";
"New Card" = "บัตรใหม่";
"New List" = "รายการใหม่";
"Edit" = "แก้ไข";
"Properties" = "คุณสมบัติ";
"Sharing..." = "แชร์...";
"Write" = "เขียน";
"Delete" = "ลบ";
"Instant Message" = "ข้อความสารบัญ: ข้อความทันที";
"Add..." = "เพิ่ม...";
"Remove" = "ลบ";
"Please wait..." = "กรุณารอสักครู่...";
"No possible subscription" = "ไม่มีการสมัครสมาชิกเป็นไปได้";
"Preferred" = "ต้องการ";
"Display" = "แสดงผล";
"Display Name" = "ชื่อที่แสดง";
"Additional Email" = "อีเมลเพิ่มเติม";
"Phone Number" = "หมายเลขโทรศัพท์";
"Prefers to receive messages formatted as" = "ต้องการรับข้อความที่จัดรูปแบบเป็น";
"Categories" = "หมวดหมู่";
"First" = "แรก";
"Last" = "สุดท้าย";
"Nickname" = "ชื่อเล่น";
"Telephone" = "โทรศัพท์";
"Work" = "งาน";
"Mobile" = "มือถือ";
"Pager" = "เพจเจอร์";
"Download iOS - MacOS configuration profile" = "ดาวน์โหลดโปรไฟล์การกำหนดค่า iOS - MacOS";
/* categories */
"contacts_category_labels" = "เพื่อนร่วมงาน, คู่แข่ง, ลูกค้า, เพื่อน, ครอบครัว, พันธมิตรทางธุรกิจ, ผู้ให้บริการ, สื่อ, บุคคลสำคัญ";
"New category" = "หมวดหมู่ใหม่";
/* adresses */
"Title" = "หัวข้อ";
"Service" = "บริการ";
"Company" = "บริษัท";
"Department" = "แผนก";
"City" = "เมือง";
"State_Province" = "รัฐ/จังหวัด";
"ZIP_Postal Code" = "รหัสไปรษณีย์";
"Country" = "ประเทศ";
"Web Page" = "หน้าเว็บ";
"Other Infos" = "อื่น ๆ ข้อมูล";
"Note" = "หมายเหตุ";
"Timezone" = "เขตเวลา";
"Birthday" = "วันเกิด";
"Birthday (yyyy-mm-dd)" = "วันเกิด (yyyy-mm-dd)";
"Freebusy URL" = "URL ที่สามารถใช้งานได้ฟรี";
"Add as..." = "เพิ่มเป็น...";
"Recipient" = "ผู้รับ";
"Carbon Copy" = "สำเนาคาร์บอน";
"Blind Carbon Copy" = "สำเนาบนซองอีเมล";
"New Addressbook..." = "สมุดที่อยู่ใหม่...";
"Subscribe to an Addressbook..." = "รับข้อมูลอัปเดตจากสมุดรายชื่อ...";
"Remove the selected Addressbook" = "ลบสมุดรายชื่อที่เลือก";
"Subscribe to a shared contact" = "สมัครสมาชิกสมุดรายชื่อที่ใช้ร่วมกัน";
"Search User" = "ค้นหาผู้ใช้";
"Name of the Address Book" = "ชื่อสมุดที่อยู่";
"Are you sure you want to delete the selected address book?"
= "คุณแน่ใจหรือว่าต้องการลบสมุดที่อยู่ที่เลือกไว้?";
"Are you sure you want to delete the addressbook \"%{0}\"?"
= "คุณแน่ใจหรือไม่ว่าต้องการลบสมุดที่อยู่ \"%{0}\"?";
"You cannot remove nor unsubscribe from a public addressbook."
= "คุณไม่สามารถลบหรือยกเลิกการสมัครสมาชิกจากสมุดที่อยู่สาธารณะได้";
"You cannot remove nor unsubscribe from your personal addressbook."
= "คุณไม่สามารถลบหรือยกเลิกการสมัครสมาชิกจากสมุดที่อยู่ส่วนตัวของคุณได้";
"Are you sure you want to delete the selected contacts?"
= "คุณแน่ใจหรือว่าต้องการลบรายชื่อที่เลือกไว้?";
"Are you sure you want to delete the card of %{0}?" = "คุณแน่ใจหรือไม่ว่าต้องการลบบัตรของ %{0}?";
"You cannot delete the card of \"%{0}\"."
= "คุณไม่สามารถลบบัตรของ \"%{0}\" ได้";
"You cannot subscribe to a folder that you own!"
= "คุณไม่สามารถสมัครสมาชิกในโฟลเดอร์ที่คุณเป็นเจ้าของ!";
"Unable to subscribe to that folder!"
= "ไม่สามารถสมัครสมาชิกในโฟลเดอร์นั้นได้.";
/* security */
"Security" = "ความปลอดภัย";
"Uninstall" = "ถอนการติดตั้ง";
"Error reading the card certificate." = "ข้อผิดพลาดในการอ่านใบรับรองของบัตร";
"No certificate associated to card." = "ไม่มีใบรับรองที่เกี่ยวข้องกับบัตร";
/* acls */
"Access rights to" = "สิทธิ์การเข้าถึง";
"For user" = "สำหรับผู้ใช้";
"Any Authenticated User" = "ผู้ใช้ที่ได้รับการยืนยันตัวตนใด ๆ";
"Public Access" = "การเข้าถึงสาธารณะ";
"This person can add cards to this addressbook."
= "บุคคลนี้สามารถเพิ่มบัตรเข้าสู่สมุดที่อยู่นี้ได้";
"This person can edit the cards of this addressbook."
= "บุคคลนี้สามารถแก้ไขบัตรของสมุดที่อยู่นี้ได้";
"This person can list the content of this addressbook."
= "บุคคลนี้สามารถรายการเนื้อหาของสมุดที่อยู่นี้ได้";
"This person can read the cards of this addressbook."
= "บุคคลนี้สามารถอ่านบัตรของสมุดที่อยู่นี้ได้.";
"This person can erase cards from this addressbook."
= "บุคคลนี้สามารถลบบัตรออกจากสมุดที่อยู่นี้ได้.";
"The selected contact has no email address."
= "ผู้ติดต่อที่เลือกไม่มีที่อยู่อีเมล์";
"Please select a contact." = "โปรดเลือกติดต่อ";
/* Messages for move and copy */
"%{0} card(s) copied" = "มีการคัดลอกบัตร %{0} ใบ";
"%{0} card(s) moved" = "มีการย้ายบัตร %{0} ใบ";
"SoAccessDeniedException" = "คุณไม่สามารถเขียนไปยังสมุดที่อยู่นี้ได้";
"Forbidden" = "เข้าถึงไม่ได้";
"Invalid Contact" = "คุณติดต่อที่เลือกไม่มีอยู่แล้ว";
"Unknown Destination Folder" = "ที่อยู่สมุดที่เลือกไว้ไม่มีอยู่แล้ว";
/* Lists */
"List details" = "รายละเอียดรายการ";
"List name" = "ชื่อรายการ";
"List nickname" = "รายชื่อเล่น";
"List description" = "รายละเอียดของรายการ";
"Members" = "สมาชิก";
"Contacts" = "ผู้ติดต่อ";
"Add" = "เพิ่ม";
"Lists can't be moved or copied." = "รายการไม่สามารถย้ายหรือคัดลอกได้";
"Export" = "ส่งออก";
"Export Address Book..." = "ส่งออกสมุดที่อยู่...";
"View Raw Source" = "ดูแหล่งที่มาแบบเรียลไทม์";
/* Import */
"Import Cards" = "นำเข้าการ์ด";
"Select a vCard or LDIF file." = "เลือกไฟล์ vCard หรือ LDIF";
"Upload" = "อัปโหลด";
"Uploading" = "กำลังอัปโหลด";
"Done" = "เสร็จแล้ว";
"An error occured while importing contacts." = "เกิดข้อผิดพลาดขณะนำเข้ารายชื่อผู้ติดต่อ";
"No card was imported." = "ไม่มีการนำเข้าบัตร";
"A total of %{0} cards were imported in the addressbook." = "จำนวนทั้งหมด %{0} บัตรถูกนำเข้าในสมุดที่อยู่";
"Reload" = "รีโหลด";
/* Properties window */
"Address Book Name" = "ชื่อสมุดที่อยู่";
"Links to this Address Book" = "ลิงค์ไปยังสมุดที่อยู่นี้";
"Authenticated User Access" = "การเข้าถึงผู้ใช้ที่ได้รับการรับรองแล้ว";
"CardDAV URL" = "CardDAV URL";
"Options" = "ตัวเลือก";
"Rename" = "เปลี่ยนชื่อ";
"Subscriptions" = "การสมัครสมาชิก";
"Global Addressbooks" = "สมุดที่อยู่อีเมลทั่วไป";
"Search" = "ค้นหา";
"Sort" = "เรียงลำดับ";
"Descending Order" = "ลำดับจากมากไปน้อย";
"Back" = "กลับ";
"Select All" = "เลือกทั้งหมด";
"Copy contacts" = "คัดลอกที่ติดต่อ";
"More messages options" = "ตัวเลือกข้อความเพิ่มเติม";
"New Contact" = "ติดต่อใหม่";
"Close" = "ปิด";
"More contact options" = "ตัวเลือกการติดต่อเพิ่มเติม";
"Organization Unit" = "หน่วยงานองค์กร";
"Add Organizational Unit" = "เพิ่มหน่วยงานองค์กร";
"Type" = "ประเภท";
"Email Address" = "ที่อยู่อีเมล์";
"New Email Address" = "ที่อยู่อีเมลใหม่";
"New Phone Number" = "หมายเลขโทรศัพท์ใหม่";
"URL" = "URL";
"New URL" = "New URL";
"street" = "ถนน";
"street (continued)" = "ถนน (ต่อไป)";
"Postoffice" = "ไปรษณีย์";
"Region" = "ภูมิภาค";
"Postal Code" = "รหัสไปรษณีย์";
"New Address" = "ที่อยู่ใหม่";
"Reset" = "รีเซ็ต";
"Description" = "คำอธิบาย";
"Add Member" = "เพิ่มสมาชิก";
"Subscribe" = "สมัครสมาชิก";
"Add Birthday" = "เพิ่มวันเกิด";
"Import" = "นำเข้า";
"More options" = "ตัวเลือกเพิ่มเติม";
"Role" = "บทบาท";
"Add Screen Name" = "เพิ่มชื่อหน้าจอ";
"Custom 1" = "กำหนดเอง 1";
"Custom 2" = "กำหนดเอง 2";
"Custom 3" = "กำหนดเอง 3";
"Custom 4" = "กำหนดเอง 4";
"Custom Value" = "ค่าที่กำหนดเอง";
"New Custom Value" = "ค่าที่กำหนดเองใหม่";
"Synchronization" = "การประสานข้อมูล";
"Synchronize" = "ซิงโครไนซ์";
"Sucessfully subscribed to address book" = "สมัครสมาชิกที่สมุดที่อยู่เรียบร้อยแล้ว";
"A similar card already exists. Would you like to save it anyway?" = "มีบัตรที่คล้ายกันอยู่แล้ว คุณต้องการบันทึกมันอยู่หรือไม่?";
/* Aria label for scope of search on contacts */
"Search scope" = "ขอบเขตการค้นหา";
/* Aria label for avatar button to select and unselect a card */
"Toggle item" = "เปิด-ปิดรายการ";
/* Hotkey to create a new card */
"key_create_card" = "c";
/* Hotkey to create a new list */
"key_create_list" = "l";
@@ -47,4 +47,4 @@ reply_info = "Dit is een antwoord op een door u verstuurde uitnodiging.";
"OK" = "OK";
"Comment" = "Commentaar:";
"Description" = "Omschrijving";
"Location" = "Location";
"Location" = "Locatie";
@@ -0,0 +1,50 @@
ACCEPTED = "수락됨";
COMPLETED = "완료됨";
DECLINED = "거절됨";
DELEGATED = "위임됨";
"IN-PROCESS" = "진행 중";
"NEEDS-ACTION" = "조치 필요";
TENTATIVE = "미정";
organized_by_you = "귀하가 주최함";
you_are_an_attendee = "귀하는 참석자입니다";
add_info_text = "iMIP '추가' 요청은 아직 SOGo에서 지원되지 않습니다.";
publish_info_text = "보낸 사람이 첨부된 이벤트를 알려드립니다.";
cancel_info_text = "귀하의 초대 또는 전체 이벤트가 취소되었습니다.";
request_info_no_attendee = "참석자에게 회의를 제안합니다. 귀하는 알림으로 이 메일을 받으셨으며, 참가자로 예정되지 않았습니다.";
Appointment = "약속";
"Status Update" = "상태 업데이트";
was = "였습니다";
Organizer = "주최자";
Time = "시간";
Attendees = "참석자";
request_info = "회의에 귀하를 초대합니다.";
"Add to calendar" = "캘린더에 추가";
"Delete from calendar" = "캘린더에서 삭제";
"Update status" = "상태 업데이트";
Accept = "수락";
Decline = "거절";
Tentative = "미정";
"Delegate ..." = "위임...";
"Delegated to" = "위임 대상";
"Update status in calendar" = "캘린더에서 상태 업데이트";
"delegated from" = "위임됨";
reply_info_no_attendee = "일정 이벤트에 대한 회신을 받았지만 회신 보낸 사람은 참가자가 아닙니다.";
reply_info = "이것은 귀하가 보낸 이벤트 초대에 대한 회신입니다.";
"to" = "받는 사람";
"Untitled" = "제목 없음";
"Size" = "크기";
"Subject" = "제목";
"From" = "보낸 사람";
"Date" = "날짜";
"To" = "받는 사람";
"Issuer" = "발급자";
/* Tooltips */
"View Attachment" = "첨부 파일 보기";
"Save Attachment" = "첨부 파일 저장";
"CC" = "참조";
"Cancel" = "취소";
"OK" = "확인";
"Comment" = "설명";
"Description" = "설명";
"Location" = "장소";
@@ -0,0 +1,50 @@
ACCEPTED = "ยอมรับ";
COMPLETED = "เสร็จสิ้น";
DECLINED = "ปฏิเสธ";
DELEGATED = "มอบหมายงาน";
"IN-PROCESS" = "ในกระบวนการ";
"NEEDS-ACTION" = "ต้องการการดำเนินการ";
TENTATIVE = "ไม่สามารถแปลได้";
organized_by_you = "จัดระเบียบโดยคุณ";
you_are_an_attendee = "คุณเป็นผู้เข้าร่วม";
add_info_text = "iMIP 'ADD' ยังไม่ได้รับการสนับสนุนโดย SOGo.";
publish_info_text = "ผู้ส่งข้อมูลแจ้งให้คุณทราบเกี่ยวกับเหตุการณ์ที่แนบมา";
cancel_info_text = "คำเชิญของคุณหรืองานทั้งหมดถูกยกเลิก";
request_info_no_attendee = "เสนอการประชุมกับผู้เข้าร่วม คุณได้รับอีเมลนี้เป็นการแจ้งเตือน คุณไม่ได";
Appointment = "การนัดหมาย";
"Status Update" = "สถานะการอัปเดต";
was = "ก่อนหน้านี้";
Organizer = "ผู้จัดงาน";
Time = "เวลา";
Attendees = "ผู้เข้าร่วม";
request_info = "เชิญคุณมาร่วมประชุม";
"Add to calendar" = "เพิ่มลงในปฏิทิน";
"Delete from calendar" = "ลบจากปฏิทิน";
"Update status" = "อัปเดตสถานะ";
Accept = "ยอมรับ";
Decline = "ปฏิเสธ";
Tentative = "ไม่สามารถแปลได้";
"Delegate ..." = "มอบหมายงาน ...";
"Delegated to" = "มอบหมายงานให้";
"Update status in calendar" = "อัปเดตสถานะในปฏิทิน";
"delegated from" = "มอบหมายโดย";
reply_info_no_attendee = "คุณได้รับการตอบกลับเกี่ยวกับกิจกรรมการจัดตารางแต่ผู้ส่งการตอบกลับไม่ใช่ผู้เข้าร่วม";
reply_info = "นี่คือการตอบกลับเชิญเข้าร่วมกิจกรรมที่คุณทำ";
"to" = "ถึง";
"Untitled" = "ไม่มีชื่อ";
"Size" = "ขนาด";
"Subject" = "หัวข้อ";
"From" = "จาก";
"Date" = "วันที่";
"To" = "ถึง";
"Issuer" = "ผู้ออก";
/* Tooltips */
"View Attachment" = "ดูไฟล์แนบ";
"Save Attachment" = "บันทึกไฟล์แนบ";
"CC" = "CC";
"Cancel" = "ยกเลิก";
"OK" = "ตกลง";
"Comment" = "ความคิดเห็น";
"Description" = "คำอธิบาย";
"Location" = "ที่อยู่";
+33 -33
View File
@@ -143,23 +143,23 @@
"This mail is being sent from an unsecure network!" = "Deze e-mail wordt verzonden vanaf een onveilig netwerk!";
"Address Book" = "Adresboek";
"Search For" = "Zoek naar";
"Contains" = "Contains";
"Does not contains" = "Does not contains";
"Advanced search" = "Advanced search";
"Anytime" = "Anytime";
"Last 7 days" = "Last 7 days";
"Last 30 days" = "Last 30 days";
"Last 6 month" = "Last 6 month";
"Before" = "Before";
"After" = "After";
"Between" = "Between";
"and" = "and";
"With attachments" = "With attachments";
"In favorites" = "In favorites";
"Unseen only" = "Unseen only";
"Show more" = "Show more";
"Contains" = "bevat";
"Does not contains" = "bevat niet";
"Advanced search" = "Geavanceerd zoeken";
"Anytime" = "Altijd";
"Last 7 days" = "Laatste 7 dagen";
"Last 30 days" = "Laatste 30 dagen";
"Last 6 month" = "Laatste 6 maanden";
"Before" = "Voor";
"After" = "Na";
"Between" = "Tussen";
"and" = "en";
"With attachments" = "Met bijlage";
"In favorites" = "In favorieten";
"Unseen only" = "Alleen ongelezen ";
"Show more" = "Meer weergeven";
"Reset" = "Reset";
"Message size" = "Message size";
"Message size" = "Berichtgrootte";
/* Popup "show" */
"all" = "alle";
@@ -171,7 +171,7 @@
/* MailListView */
"Sender" = "Afzender";
"Subject or Sender" = "Onderwerp of afzender";
"Subject or Recipient" = "Subject or Recipient";
"Subject or Recipient" = "Onderwerp of ontvanger";
"To or Cc" = "Ontvanger (Aan of Cc)";
"Entire Message" = "Volledig bericht";
"Date" = "Datum";
@@ -257,7 +257,7 @@
"Save As..." = "Opslaan als...";
"Print Preview" = "Afdrukvoorbeeld";
"View Message Source" = "Bron bekijken";
"View raw message" = "View raw message";
"View raw message" = "Bekijk onbewerkt bericht";
/* Message view "more" menu: create an event from message */
"Convert To Event" = "Omzetten naar afspraak";
@@ -464,7 +464,7 @@
"Copy messages" = "Kopieer berichten";
"More messages options" = "Meer berichtopties";
"Flag" = "Met vlag";
"Unflag" = "Unflag";
"Unflag" = "Vlag verwijderen";
"Mark as Unread" = "Als ongelezen markeren";
"Mark as Read" = "Markeren als gelezen";
"Closing Window ..." = "Venster sluiten ...";
@@ -478,7 +478,7 @@
"Your email has been sent" = "Uw email is verzonden";
"Folder compacted" = "Map gecomprimeerd";
"More Options" = "More Options";
"More Options" = "Meer opties";
"New draft" = "Nieuw concept";
"Create new draft with this template" = "Maak een nieuw concept met dit sjabloon";
@@ -517,16 +517,16 @@
"hotkey_forward" = "f";
/* Email deletion */
"Clean folder" = "Clean folder";
"Clean mailbox" = "Clean mailbox";
"Delete permanently (do not use trash)" = "Delete permanently (do not use trash)";
"Apply to subfolders" = "Apply to subfolders";
"Delete e-mails older than" = "Delete e-mails older than";
"3 months" = "3 months";
"6 months" = "6 months";
"9 months" = "9 months";
"1 year" = "1 year";
"Custom" = "Custom";
"You are about to permanently delete some messages. Are you sure you want to proceed with this action?" = "You are about to permanently delete some messages. Are you sure you want to proceed with this action?";
"Apply" = "Apply";
"%{0} message(s) deleted" = "%{0} message(s) deleted";
"Clean folder" = "Map opschonen";
"Clean mailbox" = "Mailbox opschonen";
"Delete permanently (do not use trash)" = "Permanent verwijderen (niet in de prullenbak gebruiken)";
"Apply to subfolders" = "Toepassen op submappen";
"Delete e-mails older than" = "Verwijder e-mails die ouder zijn dan";
"3 months" = "3 maanden";
"6 months" = "6 maanden";
"9 months" = "9 maanden";
"1 year" = "1 jaar";
"Custom" = "Aangepast";
"You are about to permanently delete some messages. Are you sure you want to proceed with this action?" = "U staat op het punt om enkele berichten definitief te verwijderen. Weet u zeker dat u hiermee wilt doorgaan?";
"Apply" = "Toepassen";
"%{0} message(s) deleted" = "%{0} bericht(en) verwijderd";
@@ -0,0 +1,532 @@
/* this file is in UTF-8 format! */
/* Icon's label */
"Create" = "생성";
"Empty Trash" = "휴지통 비우기";
"Empty Junk Folder" = "정크 폴더 비우기";
"Delete" = "삭제";
"Expunge" = "말소";
"Forward" = "전달";
"Get Mail" = "메일 가져오기";
"Junk" = "정크";
"Not junk" = "정크 아님";
"Reply" = "답장";
"Reply All" = "전체답장";
"Print" = "인쇄";
"Stop" = "중단";
"Write" = "글쓰기";
"Search" = "검색";
"Send" = "보내기";
"Contacts" = "연락처";
"Attach" = "첨부";
"Save" = "저장";
"Options" = "옵션";
"Close" = "닫기";
"Size" = "크기";
/* Tooltips */
"Send this message now" = "지금 이 메시지 보내기";
"Select a recipient from an Address Book" = "주소록에서 받는 사람 선택";
"Include an attachment" = "첨부 파일 포함";
"Save this message" = "이 메시지 저장";
"Get new messages" = "새 메시지 받기";
"Create a new message" = "새 메시지 만들기";
"Go to address book" = "주소록으로 이동";
"Reply to the message" = "메시지에 답장하기";
"Reply to sender and all recipients" = "발신자 및 모든 수신자에게 답장하기";
"Forward selected message" = "선택한 메시지 전달";
"Delete selected message or folder" = "선택한 메시지 또는 폴더 삭제";
"Print this message" = "이 메시지 인쇄";
"Stop the current transfer" = "현재 전송 중지";
"Attachment" = "첨부 파일";
"Unread" = "읽지 않음";
"Flagged" = "플래그가 지정된";
"Search multiple mailboxes" = "여러 메일함 검색";
/* Main Frame */
"Home" = "홈";
"Calendar" = "달력";
"Addressbook" = "주소록";
"Mail" = "메일";
"Right Administration" = "권한 관리";
"Help" = "도움말";
/* Mail account main windows */
"Welcome to the SOGo Mailer. Use the folder tree on the left to browse your mail accounts!" = "SOGo 메일러에 오신 것을 환영합니다. 왼쪽의 폴더 트리를 사용하여 메일 계정을 찾아보세요!";
"Read messages" = "메시지 읽기";
/* Tooltip for fab button */
"Write a new message" = "새 메시지 작성";
/* Tooltip for fab button */
"Write a message in new window" = "새 창에 메시지 쓰기";
"Share" = "공유";
"Account" = "계정";
"Shared Account" = "공유 계정";
/* A mailbox is selected, but no message (only shown on large screens) */
"No message selected" = "선택한 메시지가 없습니다.";
/* No mailbox is selected (usually resulting from an IMAP connection problem) */
"No mailbox selected" = "선택한 메일함이 없습니다.";
"An error occured while communicating with the mail server" = "메일 서버와 통신하는 동안 오류가 발생했습니다.";
/* Mailbox actions */
/* Compact Folder success message */
"Folder compacted" = "폴더 압축";
/* Empty Junk Folder success message */
"Junk folder emptied" = "정크 폴더 비우기";
/* Empty Trash success message */
"Trash emptied" = "휴지통 비워짐";
/* acls */
"Access rights to" = "다음에 대한 액세스 권한";
"For user" = "사용자용";
"Any Authenticated User" = "인증된 모든 사용자";
"View this folder" = "이 폴더 보기";
"Read mails from this folder" = "이 폴더에서 메일 읽기";
"Mark mails read and unread" = "읽은 메일과 읽지 않은 메일 표시";
"Modify the flags of the mails in this folder" = "이 폴더에 있는 메일의 플래그를 수정합니다.";
"Insert, copy and move mails into this folder" = "이 폴더에 메일을 삽입, 복사 및 이동합니다.";
"Post mails" = "메일 보내기";
"Add subfolders to this folder" = "이 폴더에 하위 폴더 추가";
"Remove this folder" = "이 폴더 제거";
"Erase mails from this folder" = "이 폴더에서 메일 지우기";
"Expunge this folder" = "이 폴더 삭제";
"Export This Folder" = "이 폴더 내보내기";
"Modify the acl of this folder" = "이 폴더의 acl을 수정 합니다.";
"Saved Messages.zip" = "Messages.zip으로 저장됨";
"Update" = "업데이트";
"Cancel" = "취소";
/* Mail edition */
"From" = "보낸사람";
"Subject" = "제목";
"To" = "받는사람";
"Cc" = "참조";
"Bcc" = "숨은참조";
"Reply-To" = "답장 받는 사람";
"Add address" = "주소 추가";
"Body" = "본문";
"Open" = "열기";
"Select All" = "전체 선택";
"Select Message" = "메시지 선택";
"Attach Web Page..." = "웹 페이지 첨부...";
"file" = "파일";
"files" = "파일";
"Save all" = "전체 저장";
"to" = "받는사람";
"cc" = "참조";
"bcc" = "숨은참조";
"Add a recipient" = "받는 사람 추가";
"Edit Draft..." = "초안 편집...";
"Load Images" = "이미지 불러오기";
"Return Receipt" = "받은사람 회신";
"Choose which identity to send this message from" = "이 메시지를 보낼 ID 선택";
"The sender of this message has asked to be notified when you read this message. Do you with to notify the sender?" = "이 메시지를 읽으면 발신자에게 알림을 보내도록 요청했습니다. 발신자에게 알림을 보내시겠습니까?";
"Return Receipt (displayed) - %@"= "받은사람 회신(표시됨) - %@";
"This is a Return Receipt for the mail that you sent to %@.\n\nNote: This Return Receipt only acknowledges that the message was displayed on the recipient's computer. There is no guarantee that the recipient has read or understood the message contents." = "이 메일은 %@로 보낸 메일에 대한 받은사람의 회신입니다.\n\n참고: 이 받은사람 회신은 메시지가 수신자의 컴퓨터에 표시되었다는 사실만 확인합니다. 받는 사람이 메시지 내용을 읽었거나 이해했다는 보장은 없습니다.";
"Security" = "보안";
"Sign" = "서명";
"Encrypt" = "암호화";
"Priority" = "우선순위";
"highest" = "매우 높음";
"high" = "높음";
"normal" = "보통";
"low" = "낮음";
"lowest" = "가장낮음";
"This mail is being sent from an unsecure network!" = "안전하지 않은 네트워크에서 발송된 메일입니다.";
"Address Book" = "주소록";
"Search For" = "검색";
"Contains" = "포함";
"Does not contains" = "포함하지 않음";
"Advanced search" = "고급 검색";
"Anytime" = "언제든지";
"Last 7 days" = "지난 7일";
"Last 30 days" = "지난 30일";
"Last 6 month" = "지난 6개월";
"Before" = "전";
"After" = "후";
"Between" = "사이";
"and" = "와";
"With attachments" = "첨부 파일 포함";
"In favorites" = "즐겨찾기에";
"Unseen only" = "표시되지 않음";
"Show more" = "더 보기";
"Reset" = "초기화";
"Message size" = "메시지 크기";
/* Popup "show" */
"all" = "모두";
"read" = "읽기";
"unread" = "읽지 않음";
"deleted" = "삭제됨";
"flagged" = "플래그됨";
/* MailListView */
"Sender" = "보낸사람";
"Subject or Sender" = "제목 또는 보낸사람";
"Subject or Recipient" = "제목 또는 받는 사람";
"To or Cc" = "받는 사람 또는 참조";
"Entire Message" = "전체 메시지";
"Date" = "날짜";
"View" = "보기";
"All" = "모두";
"No message" = "메시지 없음";
"messages" = "메시지";
"Yesterday" = "어제";
"first" = "처음";
"previous" = "이전";
"next" = "다음";
"last" = "마지막";
"msgnumber_to" = "to";
"msgnumber_of" = "of";
"Mark Unread" = "읽지 않음으로 표시";
"Mark Read" = "읽음으로 표시";
"Untitled" = "제목 없음";
/* Filter option in messages list */
"Show unread messages only" = "읽지 않은 메시지만 표시";
/* Filter option in messages list */
"Show flagged messages only" = "플래그가 지정된 메시지만 표시";
/* Aria label for icon of labels */
"Filtered by label" = "라벨로 필터링";
/* Tree */
"SentFolderName" = "보냄";
"TrashFolderName" = "휴지통";
"InboxFolderName" = "받은 편지함";
"DraftsFolderName" = "초안";
"JunkFolderName" = "정크";
"TemplatesFolderName" = "템플릿";
"SieveFolderName" = "필터";
"Folders" = "폴더"; /* title line */
/* MailMoveToPopUp */
"MoveTo" = "이동 &hellip;";
/* Address Popup menu */
"Add to Address Book..." = "주소록에 추가...";
"Successfully created card" = "카드 생성 성공";
"Compose Mail To" = "메일 작성 대상";
"Create Filter From Message..." = "메시지에서 필터 만들기...";
/* Image Popup menu */
"Save Image" = "이미지 저장";
"Save Attachment" = "첨부 파일 저장";
/* Mailbox popup menus */
"Open in New Mail Window" = "새 메일 창에서 열기";
"Copy Folder Location" = "폴더 위치 복사";
"Subscribe..." = "구독하기...";
"Mark Folder Read" = "폴더 읽음 표시";
"New Folder..." = "새 폴더...";
"Compact This Folder" = "이 폴더 압축";
"Search Messages..." = "메시지 검색...";
"Sharing..." = "공유...";
"New Subfolder..." = "새 하위 폴더...";
"Rename Folder..." = "폴더 이름변경";
"Delete Folder" = "폴더 삭제";
"Use This Folder For" = "이 폴더를 다음 용도로 사용";
"Get Messages for Account" = "계정 메시지 받기";
"Properties..." = "속성...";
"Delegation..." = "위임...";
/* Use This Folder menu */
"Sent Messages" = "메시지 보내기";
"Drafts" = "초안";
"Deleted Messages" = "삭제된 메시지";
"Junk Messages" = "정크 메시지";
/* Message list popup menu */
"Open Message In New Window" = "새 창에서 메시지 열기";
"Reply to Sender Only" = "보낸 사람에게만 답장";
"Reply to All" = "모두에게 답장";
"Edit As New..." = "새로 편집...";
"Move To" = "이동";
"Copy To" = "복사";
"Label" = "라벨";
"Mark" = "표시";
"Save As..." = "다른 이름으로 저장";
"Print Preview" = "인쇄 미리보기";
"View Message Source" = "메시지 소스 보기";
"View raw message" = "원시 메시지 보기";
/* Message view "more" menu: create an event from message */
"Convert To Event" = "이벤트로 변환";
/* Message view "more" menu: create a task from message */
"Convert To Task" = "작업으로 변환";
/* Message view "more" menu: download message as an eml file */
"Download message" = "메시지 다운로드";
/* Message view "more" menu: download message as a zip archive */
"Download message (zip)" = "메시지 다운로드(zip)";
/* Message view "more" menu: download all attachments as a zip archive */
"Download all attachments" = "모든 첨부파일 다운로드";
/* Filename prefix when downloading all attachments as a zip archive */
"attachments" = "첨부";
"Print..." = "인쇄";
"Delete Message" = "메시지 삭제";
"Delete Selected Messages" = "선택한 메시지 삭제";
"Mark the selected messages as junk" = "선택한 메시지를 정크 메시지로 표시";
"Mark the selected messages as not junk" = "선택한 메시지를 정크 메일이 아닌 것으로 표시";
/* Text appended to the recipients list when there are too many recipients */
"and %{0} more..." = "및 %{0} 더보기...";
/* Button label to hide extended list of recipients */
"Hide" = "숨기기";
/* Number of selected messages in list */
"selected" = "선택된";
/* Date formatting from one time to another time */
"to_time" = "to";
/* Date formatting from one day to another day */
"to_date" = "to";
/* Encrypted message notification */
"This message is encrypted" = "이 메시지는 암호화되어 있습니다.";
/* Encrypted message but no certificate */
"This message can't be decrypted. Please make sure you have uploaded your S/MIME certificate from the mail preferences module." = "이 메시지는 해독할 수 없습니다. 메일 환경설정 모듈에서 S/MIME 인증서를 업로드했는지 확인하세요.";
/* OpenSSL certificate error - unknown issuer */
"certificate verify error" = "메시지 서명을 확인할 수 없음";
/* OpenSSL certificate error - digest failure */
"digest failure" = "메시지가 수정되었습니다.";
/* OpenSSL reading error */
"Error reading the certificate. Please install a new certificate." = "인증서를 읽는 동안 오류가 발생했습니다. 새 인증서를 설치하세요.";
/* Trying to access a non-existent certificate */
"No certificate associated to account." = "계정에 연결된 인증서가 없습니다.";
/* Invalid S/MIME signature */
"Digital signature is not valid" = "디지털 서명이 유효하지 않습니다.";
/* Valid S/MIME signature */
"Message is signed" = "메시지가 서명됨";
/* Valid S/MIME signature but common name not found */
"Message is signed but the certificate doesn't match the sender email address" = "메시지에 서명이 되어 있지만, 인증서가 발신자 이메일 주소와 일치하지 않습니다.";
/* Unknown error while validating message signature */
"Digital signature is not valid" = "디지털 서명이 유효하지 않습니다.";
"This Folder" = "이 폴더";
/* Label popup menu */
"None" = "없음";
/* Mark popup menu */
"As Read" = "읽음으로 표시";
"Thread As Read" = "스레드를 읽음으로 표시";
"As Read By Date..." = "읽은 순서대로...";
"All Read" = "모두 읽기";
"As Junk" = "정크로 설정";
"As Not Junk" = "정크 아님으로 설정";
"Run Junk Mail Controls" = "정크 메일 컨트롤 실행";
"Search messages in" = "다음에서 메시지 검색";
"Search" = "검색";
"Search subfolders" = "하위 폴더 검색";
"Match any of the following" = "다음 중 하나에 해당합니다.";
"Match all of the following" = "다음 중 모두 일치하는 것을 고르세요.";
"contains" = "포함";
"does not contain" = "포함하지 않음";
"No matches found" = "일치하는 항목이 없음";
"results found" = "검색 결과";
"result found" = "검색 결과";
"Please specify at least one filter" = "필터를 하나 이상 지정하세요.";
/* Folder operations */
"Name" = "이름";
"Enter the new name of your folder"
="폴더의 새 이름을 입력합니다.";
"Do you really want to move this folder into the trash ?"
= "이 폴더를 정말로 휴지통으로 옮길까요?";
"Operation failed" = "작업 실패";
"Quota" = "할당량:";
"quotasFormat" = "%{0}% : %{1} MB 사용됨";
"messageQuotasFormat" = "%{1} 메세지 중 %{0}%";
"Unable to move/delete folder." = "폴더를 이동/삭제할 수 없습니다.";
/* Alternative operation when folder cannot be deleted */
"The mailbox could not be moved to the trash folder. Would you like to delete it immediately?"
= "메일함을 휴지통으로 옮길 수 없습니다. 즉시 삭제하시겠습니까?";
/* Confirmation message when deleting multiple messages */
"Are you sure you want to delete the selected messages?" = "선택한 메시지를 삭제하시겠습니까?";
/* Notification on the number of messages successfuly copied */
"%{0} message(s) copied" = "%{0} 메시지 복사됨";
/* Notification on the number of messages successfuly movied */
"%{0} message(s) moved" = "%{0} 메시지 이동됨";
"Please select a message." = "메시지를 선택해 주세요.";
"Please select a message to print." = "인쇄할 메시지를 선택하세요.";
"Please select only one message to print." = "인쇄할 메시지를 하나만 선택하세요.";
"The message you have selected doesn't exist anymore." = "선택한 메시지가 더 이상 존재하지 않습니다.";
"The folder with name \"%{0}\" could not be created."
= "\"%{0}\" 이름의 폴더를 만들지 못했습니다.";
"This folder could not be renamed to \"%{0}\"."
= "이 폴더의 이름을 \"%{0}\"로 변경할 수 없습니다.";
"The folder could not be deleted."
= "폴더를 삭제할 수 없습니다.";
"The trash could not be emptied."
= "휴지통을 비울 수 없습니다.";
"The folder functionality could not be changed."
= "폴더 기능을 변경할 수 없습니다.폴더 기능은 변경할 수 없습니다.";
"You need to choose a non-virtual folder!" = "가상 폴더가 아닌 폴더를 선택해야 합니다!";
"Moving a message into its own folder is impossible!"
= "메시지를 자체 폴더로 옮기는 것은 불가능합니다!";
"Copying a message into its own folder is impossible!"
= "메시지를 자체 폴더에 복사하는 것은 불가능합니다!";
/* Message operations */
"The messages could not be moved to the trash folder. Would you like to delete them immediately?"
= "메시지를 휴지통 폴더로 옮길 수 없습니다. 즉시 삭제하시겠습니까?";
/* Message editing */
"Please specify a subject." = "제목을 지정해 주세요.";
"error_missingsubject" = "메시지에 제목이 없습니다. 정말 보내시겠습니까?";
"error_missingrecipients" = "받는 사람을 한 명 이상 지정하세요.";
"Send Anyway" = "아무튼 보내기";
"Error while saving the draft" = "초안 저장 중 오류 발생";
/* Error when emptying trash */
"Unable to empty the trash folder." = "휴지통 폴더를 비울 수 없습니다.";
/* Error when emptying junk folder */
"Unable to empty the junk folder." = "정크 폴더를 비울 수 없습니다.";
/* Error when uploading a file attachment */
"Error while uploading the file \"%{0}\":" = "\"%{0}\" 파일을 업로드하는 동안 오류가 발생했습니다.";
"There is an active file upload. Closing the window will interrupt it." = "활성 파일 업로드가 진행 중입니다. 창을 닫으면 업로드가 중단됩니다.";
"Message is too big" = "메시지가 너무 큽니다.";
/* Appears while sending the message */
"Sending" = "전송 중";
/* Appears when the message is successfuly sent */
"Sent" = "전송됨";
"cannot send message: (smtp) all recipients discarded" = "메시지를 보낼 수 없음: 모든 수신자가 유효하지 않습니다.";
"cannot send message (smtp) - recipients discarded" = "메시지를 보낼 수 없습니다. 다음 주소는 유효하지 않습니다.";
"cannot send message: (smtp) error when connecting" = "메시지를 보낼 수 없음: SMTP 서버에 연결할 때 오류가 발생했습니다.";
"cannot sign email without certificate" = "메일 계정에 연결된 인증서가 없기 때문에 메시지에 서명할 수 없습니다.";
"cannot sign message because the certificate can't be read" = "메일 계정에 연결된 인증서를 읽을 수 없기 때문에 메시지에 서명할 수 없습니다.";
"cannot sign message because the certificate doesn't include the specified sender address" = "보낸 사람 주소가 메일 계정에 연결된 인증서에 포함되어 있지 않으므로 메시지에 서명할 수 없습니다.";
/* Contacts list in mail editor */
"Email" = "이메일";
"More mail options" = "더 많은 메일 옵션";
"Delegation" = "위임";
"Add User" = "사용자 추가";
"Add a tag" = "태그 추가";
"reply" = "답장";
"Edit" = "수정";
"Yes" = "예";
"No" = "아니오";
"Location" = "위치";
"Rename" = "이름 변경";
"Compact" = "압축";
"Export" = "내보내기";
"Set as Drafts" = "초안으로 설정";
"Set as Sent" = "보내기로 설정";
"Set as Trash" = "휴지통으로 설정";
/* Set the folder as the one holding the Templates */
"Set as Templates" = "템플릿으로 설정";
/* Set the folder as the one holding Junk mails */
"Set as Junk" = "정크로 설정";
"Sort" = "정렬";
"Order Received" = "수신된 순서";
"Descending Order" = "내림차순";
"Back" = "뒤로";
"Copy messages" = "메시지 복사";
"More messages options" = "더 많은 메시지 옵션";
"Flag" = "플래그";
"Unflag" = "플래그 해제";
"Mark as Unread" = "읽지 않음으로 표시";
"Mark as Read" = "읽음으로 표시";
"Closing Window ..." = "윈도우 닫는 중";
"Tried to send too many mails. Please wait." = "메일을 너무 많이 보내려고 했습니다. 잠시만 기다려주세요.";
"View Mail" = "메일 보기";
"This message contains external images." = "이 메시지에는 외부 이미지가 포함되어 있습니다.";
"Expanded" = "확장";
"Add a Criteria" = "기준 추가";
"More search options" = "더 많은 검색 옵션";
"Your email has been saved" = "이메일이 저장되었습니다.";
"Your email has been sent" = "이메일이 전송되었습니다.";
"Folder compacted" = "폴더 압축";
"More Options" = "더 많은 옵션";
"New draft" = "새 초안";
"Create new draft with this template" = "이 템플릿으로 새 초안 만들기";
/* Advanced search */
"Enter Subject" = "제목 입력";
"Enter From" = "보낸사람 입력";
"Enter To" = "받는사람 입력";
"Enter Cc" = "참조 입력";
"Enter Body" = "본문 입력";
"match" = "일치";
"does not match" = "일치하지 않음";
/* Aria label for scope of search on messages */
"Search scope" = "검색 범위";
/* Subscriptions Dialog */
"Manage Subscriptions" = "구독 관리";
/* Label of filter input field in subscriptions dialog */
"Filter" = "필터";
/* Hotkey to write a new message */
"hotkey_compose" = "w";
/* Hotkey to flag a message */
"hotkey_flag" = "*";
/* Hotkey to reply to a message */
"hotkey_reply" = "r";
/* Hotkey to reply to all recipients of a message */
"hotkey_replyall" = "a";
/* Hotkey to forward to a message */
"hotkey_forward" = "f";
/* Email deletion */
"Clean folder" = "폴더 지우기";
"Clean mailbox" = "메일함 정리";
"Delete permanently (do not use trash)" = "영구 삭제(휴지통 사용 안 함)";
"Apply to subfolders" = "하위 폴더에 적용";
"Delete e-mails older than" = "다음보다 오래된 이메일 삭제";
"3 months" = "3개월";
"6 months" = "6개월";
"9 months" = "9개월";
"1 year" = "1년";
"Custom" = "사용자 지정";
"You are about to permanently delete some messages. Are you sure you want to proceed with this action?" = "일부 메시지를 영구 삭제하려고 합니다. 이 작업을 계속 진행하시겠습니까?";
"Apply" = "적용";
"%{0} message(s) deleted" = "%{0} 메시지 삭제됨";
+532
View File
@@ -0,0 +1,532 @@
/* this file is in UTF-8 format! */
/* Icon's label */
"Create" = "สร้าง";
"Empty Trash" = "ล้างถังขยะ";
"Empty Junk Folder" = "ล้างอีเมลขยะ";
"Delete" = "ลบ";
"Expunge" = "ลบออก";
"Forward" = "ส่งต่อ";
"Get Mail" = "รับเมล";
"Junk" = "อีเมลขยะ";
"Not junk" = "ไม่ใช่อีเมลขยะ";
"Reply" = "ตอบกลับ";
"Reply All" = "ตอบกลับทั้งหมด";
"Print" = "พิมพ์";
"Stop" = "หยุด";
"Write" = "เขียน";
"Search" = "ค้นหา";
"Send" = "ส่ง";
"Contacts" = "ผู้ติดต่อ";
"Attach" = "แนบ";
"Save" = "บันทึก";
"Options" = "ตัวเลือก";
"Close" = "ปิด";
"Size" = "ขนาด";
/* Tooltips */
"Send this message now" = "ส่งข้อความนี้ตอนนี้";
"Select a recipient from an Address Book" = "เลือกผู้รับจากสมุดที่อยู่";
"Include an attachment" = "รวมไฟล์แนบ";
"Save this message" = "บันทึกข้อความนี้";
"Get new messages" = "รับข้อความใหม่";
"Create a new message" = "สร้างข้อความใหม่";
"Go to address book" = "ไปที่สมุดที่อยู่";
"Reply to the message" = "ตอบกลับข้อความ";
"Reply to sender and all recipients" = "ตอบกลับผู้ส่งและผู้รับทั้งหมด";
"Forward selected message" = "ส่งข้อความที่เลือกไว้ข้างหน้า";
"Delete selected message or folder" = "ลบข้อความหรือโฟลเดอร์ที่เลือก";
"Print this message" = "พิมพ์ข้อความนี้";
"Stop the current transfer" = "หยุดการโอนปัจจุบัน";
"Attachment" = "สิ่งที่แนบ";
"Unread" = "ยังไม่ได้อ่าน";
"Flagged" = "ทำเครื่องหมาย";
"Search multiple mailboxes" = "ค้นหากล่องจดหมายหลายกล่อง";
/* Main Frame */
"Home" = "หน้าหลัก";
"Calendar" = "ปฏิทิน";
"Addressbook" = "สมุดรายชื่อ";
"Mail" = "จดหมาย";
"Right Administration" = "การจัดการสิทธ์";
"Help" = "ช่วยเหลือ";
/* Mail account main windows */
"Welcome to the SOGo Mailer. Use the folder tree on the left to browse your mail accounts!" = "ยินดีต้อนรับสู่ SOGo Mailer ใช้ต้นไม้โฟลเดอร์ทางซ้ายเพื่อเรียกดูบัญชีอีเมลของคุณ!";
"Read messages" = "อ่านข้อความ";
/* Tooltip for fab button */
"Write a new message" = "สร้างข้อความใหม่";
/* Tooltip for fab button */
"Write a message in new window" = "เขียนข้อความในหน้าต่างใหม่";
"Share" = "แชร์";
"Account" = "บัญชี";
"Shared Account" = "บัญชีที่ใช้ร่วมกัน";
/* A mailbox is selected, but no message (only shown on large screens) */
"No message selected" = "ไม่มีข้อความที่เลือก";
/* No mailbox is selected (usually resulting from an IMAP connection problem) */
"No mailbox selected" = "ไม่ได้เลือกกล่องจดหมาย";
"An error occured while communicating with the mail server" = "เกิดข้อผิดพลาดขึ้นในขณะที่กำลังสื่อสารกับเซิร์ฟเวอร์ของเมล์";
/* Mailbox actions */
/* Compact Folder success message */
"Folder compacted" = "โฟลเดอร์ถูกบีบอัด";
/* Empty Junk Folder success message */
"Junk folder emptied" = "โฟลเดอร์ขยะถูกล้าง";
/* Empty Trash success message */
"Trash emptied" = "ถังขยะถูกล้าง";
/* acls */
"Access rights to" = "สิทธิ์การเข้าถึง";
"For user" = "สำหรับผู้ใช้";
"Any Authenticated User" = "ผู้ใช้ที่ได้รับการยืนยันตัวตนใด ๆ";
"View this folder" = "ดูโฟลเดอร์นี้";
"Read mails from this folder" = "อ่านอีเมลจากโฟลเดอร์นี้";
"Mark mails read and unread" = "ทำเครื่องหมายอีเมลอ่านและยังไม่อ่าน";
"Modify the flags of the mails in this folder" = "ปรับเปลี่ยนธงของอีเมลในโฟลเดอร์นี้";
"Insert, copy and move mails into this folder" = "ใส่ คัดลอก และย้ายอีเมลล์เข้าไปในโฟลเดอร์นี้";
"Post mails" = "ส่งจดหมาย";
"Add subfolders to this folder" = "เพิ่มโฟลเดอร์ย่อยในโฟลเดอร์นี้";
"Remove this folder" = "ลบโฟลเดอร์นี้";
"Erase mails from this folder" = "ลบอีเมลจากโฟลเดอร์นี้";
"Expunge this folder" = "ลบโฟลเดอร์นี้";
"Export This Folder" = "ส่งออกโฟลเดอร์นี้";
"Modify the acl of this folder" = "ปรับเปลี่ยน acl ของโฟลเดอร์นี้";
"Saved Messages.zip" = "Saved Messages.zip";
"Update" = "อัปเดต";
"Cancel" = "ยกเลิก";
/* Mail edition */
"From" = "จาก";
"Subject" = "หัวข้อ";
"To" = "ถึง";
"Cc" = "สำเนา";
"Bcc" = "สำเนาช่อน";
"Reply-To" = "ตอบกลับ";
"Add address" = "เพิ่มที่อยู่";
"Body" = "เนื้อหา";
"Open" = "เปิด";
"Select All" = "เลือกทั้งหมด";
"Select Message" = "เลือกข้อความ";
"Attach Web Page..." = "แนบหน้าเว็บ...";
"file" = "ไฟล์";
"files" = "ไฟล์";
"Save all" = "บันทึกทั้งหมด";
"to" = "ถึง";
"cc" = "สำเนา";
"bcc" = "สำเนาซ่อน";
"Add a recipient" = "เพิ่มผู้รับ";
"Edit Draft..." = "แก้ไขร่าง...";
"Load Images" = "โหลดรูปภาพ";
"Return Receipt" = "ส่งคืน";
"Choose which identity to send this message from" = "เลือกตัวตนที่จะส่งข้อความนี้จาก";
"The sender of this message has asked to be notified when you read this message. Do you with to notify the sender?" = "ผู้ส่งข้อความนี้ขอให้แจ้งเตือนเมื่อคุณอ่านข้อความนี้ คุณต้องการแจ้งเตือนผู้ส่งหรือไม่?";
"Return Receipt (displayed) - %@"= "ส่งคืน (แสดง) - %@";
"This is a Return Receipt for the mail that you sent to %@.\n\nNote: This Return Receipt only acknowledges that the message was displayed on the recipient's computer. There is no guarantee that the recipient has read or understood the message contents." = "นี่คือใบรับรองการส่งคืนสำหรับจดหมายที่คุณส่งไปยัง %@.\n\nหมายเหตุ: ใบรับรองการส่งคืนนี้เพียงแค่ยืนยันว่าข้อความได้แสดงบนคอมพิวเตอร์ของผู้รับเท่านั้น ไม่มีการรับประกันว่าผู้รับได้อ่านหรือเข้าใจเนื้อหาข้อความ";
"Security" = "ความปลอดภัย";
"Sign" = "ลงชื่อ";
"Encrypt" = "เข้ารหัส";
"Priority" = "ความสำคัญ";
"highest" = "สูงสุด";
"high" = "สูง";
"normal" = "ปกติ";
"low" = "ต่ำ";
"lowest" = "ต่ำสุด";
"This mail is being sent from an unsecure network!" = "ข้อความนี้ถูกส่งจากเครือข่ายที่ไม่ปลอดภัย!";
"Address Book" = "สมุดรายชื่อ";
"Search For" = "ค้นหา";
"Contains" = "มี";
"Does not contains" = "ไม่มี";
"Advanced search" = "การค้นหาขั้นสูง";
"Anytime" = "เวลาใดก็ได้";
"Last 7 days" = "7 วันที่ผ่านมา";
"Last 30 days" = "30 วันที่ผ่านมา";
"Last 6 month" = "6 เดือนที่ผ่านมา";
"Before" = "ก่อน";
"After" = "หลัง";
"Between" = "ระหว่าง";
"and" = "และ";
"With attachments" = "พร้อมไฟล์แนบ";
"In favorites" = "อยู่ในรายการโปรด";
"Unseen only" = "เฉพาะไม่เคยอ่าน";
"Show more" = "แสดงเพิ่มเติม";
"Reset" = "รีเซ็ท";
"Message size" = "ขนาดข้อความ";
/* Popup "show" */
"all" = "ทั้งหมด";
"read" = "อ่าน";
"unread" = "ยังไม่ได้อ่าน";
"deleted" = "ลบ";
"flagged" = "ทำเครื่องหมาย";
/* MailListView */
"Sender" = "ผู้ส่ง";
"Subject or Sender" = "หัวข้อหรือผู้ส่ง";
"Subject or Recipient" = "หัวข้อหรือผู้รับ";
"To or Cc" = "ถึงหรือสำเนา";
"Entire Message" = "ข้อความทั้งหมด";
"Date" = "วันที่";
"View" = "มุมมอง";
"All" = "ทั้งหมด";
"No message" = "ไม่มีข้อความ";
"messages" = "ข้อความ";
"Yesterday" = "เมื่อวานนี้";
"first" = "แรก";
"previous" = "ก่อนหน้านี้";
"next" = "ถัดไป";
"last" = "สุดท้าย";
"msgnumber_to" = "ถึง";
"msgnumber_of" = "ของ";
"Mark Unread" = "ทำเครื่องหมายว่ายังไม่ได้อ่าน";
"Mark Read" = "Mark Read";
"Untitled" = "ไม่มีชื่อ";
/* Filter option in messages list */
"Show unread messages only" = "แสดงข้อความที่ยังไม่ได้อ่านเท่านั้น";
/* Filter option in messages list */
"Show flagged messages only" = "แสดงข้อความที่ถูกทำเครื่องหมายเท่านั้น";
/* Aria label for icon of labels */
"Filtered by label" = "กรองตามป้ายชื่อ";
/* Tree */
"SentFolderName" = "ส่ง";
"TrashFolderName" = "ถังขยะ";
"InboxFolderName" = "กล่องขาเข้า";
"DraftsFolderName" = "ร่าง";
"JunkFolderName" = "อีเมลขยะ";
"TemplatesFolderName" = "เทมเพลต";
"SieveFolderName" = "ตัวกรอง";
"Folders" = "โฟลเดอร์"; /* title line */
/* MailMoveToPopUp */
"MoveTo" = "เคลื่อนที่ &hellip;";
/* Address Popup menu */
"Add to Address Book..." = "เพิ่มไปยังสมุดรายชื่อ...";
"Successfully created card" = "สร้างบัตรเรียบร้อยแล้ว";
"Compose Mail To" = "สร้างอีเมลถึง";
"Create Filter From Message..." = "สร้างตัวกรองจากข้อความ ...";
/* Image Popup menu */
"Save Image" = "บันทึกภาพ";
"Save Attachment" = "บันทึกไฟล์แนบ";
/* Mailbox popup menus */
"Open in New Mail Window" = "เปิดในหน้าต่างจดหมายใหม่";
"Copy Folder Location" = "คัดลอกตำแหน่งโฟลเดอร์";
"Subscribe..." = "สมัครสมาชิก...";
"Mark Folder Read" = "ทำเครื่องหมายโฟลเดอร์ว่าอ่านแล้ว";
"New Folder..." = "โฟลเดอร์ใหม่...";
"Compact This Folder" = "เก็บรวบรวมโฟลเดอร์นี้";
"Search Messages..." = "ค้นหาข้อความ...";
"Sharing..." = "แชร์...";
"New Subfolder..." = "สร้างโฟลเดอร์ย่อยใหม่";
"Rename Folder..." = "เปลี่ยนชื่อโฟลเดอร์...";
"Delete Folder" = "ลบโฟลเดอร์";
"Use This Folder For" = "ใช้โฟลเดอร์นี้สำหรับ";
"Get Messages for Account" = "รับข้อความสำหรับบัญชี";
"Properties..." = "คุณสมบัติ...";
"Delegation..." = "การมอบหมาย...";
/* Use This Folder menu */
"Sent Messages" = "ข้อความที่ถูกส่ง";
"Drafts" = "ร่าง";
"Deleted Messages" = "ข้อความที่ถูกลบ";
"Junk Messages" = "ข้อความขยะ";
/* Message list popup menu */
"Open Message In New Window" = "เปิดข้อความในหน้าต่างใหม่";
"Reply to Sender Only" = "ตอบกลับเฉพาะผู้ส่งเท่านั้น";
"Reply to All" = "ตอบกลับทั้งหมด";
"Edit As New..." = "แก้ไขเป็นใหม่...";
"Move To" = "ย้ายไป";
"Copy To" = "คัดลอกไปยัง";
"Label" = "ป้าย";
"Mark" = "มาร์ค";
"Save As..." = "บันทึกเป็น...";
"Print Preview" = "การพิมพ์ตัวอย่างก่อนพิมพ์";
"View Message Source" = "ดูแหล่งที่มาของข้อความ";
"View raw message" = "ดูข้อความดิบ";
/* Message view "more" menu: create an event from message */
"Convert To Event" = "แปลเป็นกิจกรรม";
/* Message view "more" menu: create a task from message */
"Convert To Task" = "แปลเป็นงาน";
/* Message view "more" menu: download message as an eml file */
"Download message" = "ดาวน์โหลดข้อความ";
/* Message view "more" menu: download message as a zip archive */
"Download message (zip)" = "ดาวน์โหลดข้อความ (zip)";
/* Message view "more" menu: download all attachments as a zip archive */
"Download all attachments" = "ดาวน์โหลดไฟล์แนบทั้งหมด";
/* Filename prefix when downloading all attachments as a zip archive */
"attachments" = "สิ่งที่แนบ";
"Print..." = "พิมพ์...";
"Delete Message" = "ข้อความที่ถูกลบ";
"Delete Selected Messages" = "ลบข้อความที่เลือก";
"Mark the selected messages as junk" = "ทำเครื่องหมายข้อความที่เลือกเป็นอีเมลขยะ";
"Mark the selected messages as not junk" = "ทำเครื่องหมายข้อความที่เลือกเป็นไม่ใช่อีเมลขยะ";
/* Text appended to the recipients list when there are too many recipients */
"and %{0} more..." = "และ %{0} เพิ่มเติม...";
/* Button label to hide extended list of recipients */
"Hide" = "ซ่อน";
/* Number of selected messages in list */
"selected" = "เลือก";
/* Date formatting from one time to another time */
"to_time" = "ถึง";
/* Date formatting from one day to another day */
"to_date" = "ถึง";
/* Encrypted message notification */
"This message is encrypted" = "ข้อความนี้ถูกเข้ารหัสแล้ว";
/* Encrypted message but no certificate */
"This message can't be decrypted. Please make sure you have uploaded your S/MIME certificate from the mail preferences module." = "ข้อความนี้ไม่สามารถถอดรหัสได้ โปรดตรวจสอบให้แน่ใจว่าคุณได้อัปโหลดใบรับรอง S/MIME ของคุณจากโมดูลการตั้งค่าอีเมล์แล้ว";
/* OpenSSL certificate error - unknown issuer */
"certificate verify error" = "ไม่สามารถยืนยันลายเซ็นข้อความได้";
/* OpenSSL certificate error - digest failure */
"digest failure" = "ข้อความถูกแก้ไขแล้ว";
/* OpenSSL reading error */
"Error reading the certificate. Please install a new certificate." = "ข้อผิดพลาดในการอ่านใบรับรอง โปรดติดตั้งใบรับรองใหม่";
/* Trying to access a non-existent certificate */
"No certificate associated to account." = "ไม่มีใบรับรองที่เกี่ยวข้องกับบัญชี";
/* Invalid S/MIME signature */
"Digital signature is not valid" = "ลายเซ็นดิจิทัลไม่ถูกต้อง";
/* Valid S/MIME signature */
"Message is signed" = "ข้อความถูกลงลายมือ";
/* Valid S/MIME signature but common name not found */
"Message is signed but the certificate doesn't match the sender email address" = "ข้อความถูกลงลายมือแต่ใบรับรองไม่ตรงกับที่อยู่อีเมลผู้ส่ง";
/* Unknown error while validating message signature */
"Digital signature is not valid" = "ลายเซ็นดิจิทัลไม่ถูกต้อง";
"This Folder" = "โฟลเดอร์นี้";
/* Label popup menu */
"None" = "ไม่มี";
/* Mark popup menu */
"As Read" = "อ่าน";
"Thread As Read" = "เรียบเรียงเป็นอ่านแล้ว";
"As Read By Date..." = "เมื่ออ่านตามวันที่...";
"All Read" = "ทั้งหมดอ่าน";
"As Junk" = "เป็นอีเมลขยะ";
"As Not Junk" = "ไม่ใช่อีเมลขยะ";
"Run Junk Mail Controls" = "เรียกใช้ควบคุมอีเมลขยะ";
"Search messages in" = "ค้นหาข้อความใน";
"Search" = "ค้นหา";
"Search subfolders" = "ค้นหาโฟลเดอร์ย่อย";
"Match any of the following" = "ตรงกับหนึ่งในต่อไปนี้";
"Match all of the following" = "ตรงกับทั้งหมดของต่อไปนี้";
"contains" = "ประกอบด้วย";
"does not contain" = "ไม่ประกอบด้วย";
"No matches found" = "ไม่พบการจับคู่";
"results found" = "ผลลัพธ์ที่พบ";
"result found" = "ผลลัพธ์ที่พบ";
"Please specify at least one filter" = "โปรดระบุอย่างน้อยหนึ่งตัวกรอง";
/* Folder operations */
"Name" = "ชื่อ";
"Enter the new name of your folder"
="ป้อนชื่อใหม่ของโฟลเดอร์ของคุณ";
"Do you really want to move this folder into the trash ?"
= "คุณต้องการย้ายโฟลเดอร์นี้ไปยังถังขยะใช่ไหม?";
"Operation failed" = "การดำเนินการล้มเหลว";
"Quota" = "โควต้า:";
"quotasFormat" = "%{0}% ใช้ไปที่ %{1} MB";
"messageQuotasFormat" = "%{0}% of %{1} msgs";
"Unable to move/delete folder." = "ไม่สามารถย้าย / ลบโฟลเดอร์ได้";
/* Alternative operation when folder cannot be deleted */
"The mailbox could not be moved to the trash folder. Would you like to delete it immediately?"
= "กล่องจดหมายไม่สามารถย้ายไปยังโฟลเดอร์ถังขยะได้ คุณต้องการลบมันทันทีหรือไม่?";
/* Confirmation message when deleting multiple messages */
"Are you sure you want to delete the selected messages?" = "คุณแน่ใจหรือว่าต้องการลบข้อความที่เลือกไว้?";
/* Notification on the number of messages successfuly copied */
"%{0} message(s) copied" = "%{0} message(s) copied";
/* Notification on the number of messages successfuly movied */
"%{0} message(s) moved" = "%{0} message(s) moved";
"Please select a message." = "โปรดเลือกข้อความ";
"Please select a message to print." = "โปรดเลือกข้อความที่ต้องการพิมพ์";
"Please select only one message to print." = "โปรดเลือกข้อความที่ต้องการพิมพ์เพียงหนึ่งข้อเท่านั้น.";
"The message you have selected doesn't exist anymore." = "ข้อความที่คุณเลือกไม่มีอยู่แล้ว";
"The folder with name \"%{0}\" could not be created."
= "โฟลเดอร์ที่ชื่อ \"%{0}\" ไม่สามารถสร้างได้";
"This folder could not be renamed to \"%{0}\"."
= "โฟลเดอร์นี้ไม่สามารถเปลี่ยนชื่อเป็น \"%{0}\" ได้";
"The folder could not be deleted."
= "โฟลเดอร์ไม่สามารถลบได้";
"The trash could not be emptied."
= "ไม่สามารถล้างขยะได้";
"The folder functionality could not be changed."
= "ฟังก์ชันการทำงานของโฟลเดอร์ไม่สามารถเปลี่ยนแปลงได้";
"You need to choose a non-virtual folder!" = "คุณต้องเลือกโฟลเดอร์ที่ไม่ใช่เสมือนจริง!";
"Moving a message into its own folder is impossible!"
= "การย้ายข้อความไปยังโฟลเดอร์ของมันเองเป็นสิ่งที่เป็นไปไม่ได้!";
"Copying a message into its own folder is impossible!"
= "การคัดลอกข้อความไปยังโฟลเดอร์ของมันเองเป็นสิ่งที่เป็นไปไม่ได้!";
/* Message operations */
"The messages could not be moved to the trash folder. Would you like to delete them immediately?"
= "กล่องจดหมายไม่สามารถย้ายไปยังโฟลเดอร์ถังขยะได้ คุณต้องการลบมันทันทีหรือไม่?";
/* Message editing */
"Please specify a subject." = "โปรดระบุหัวข้อ";
"error_missingsubject" = "ข้อความไม่มีหัวข้อ คุณแน่ใจหรือว่าต้องการส่ง?";
"error_missingrecipients" = "โปรดระบุผู้รับอย่างน้อยหนึ่งคน";
"Send Anyway" = "ส่งอย่างไรก็ตาม";
"Error while saving the draft" = "ข้อผิดพลาดในขณะที่บันทึกแบบร่าง";
/* Error when emptying trash */
"Unable to empty the trash folder." = "ไม่สามารถล้างโฟลเดอร์ถังขยะได้";
/* Error when emptying junk folder */
"Unable to empty the junk folder." = "ไม่สามารถล้างโฟลเดอร์ถังขยะได้";
/* Error when uploading a file attachment */
"Error while uploading the file \"%{0}\":" = "ข้อผิดพลาดในขณะที่อัปโหลดไฟล์ \"%{0}\":";
"There is an active file upload. Closing the window will interrupt it." = "มีการอัปโหลดไฟล์ที่กำลังทำงานอยู่ การปิดหน้าต่างจะทำให้การอัปโหลดถูกขัดจังหวะ";
"Message is too big" = "ข้อความใหญ่เกินไป";
/* Appears while sending the message */
"Sending" = "กำลังส่ง...";
/* Appears when the message is successfuly sent */
"Sent" = "ส่ง";
"cannot send message: (smtp) all recipients discarded" = "ไม่สามารถส่งข้อความได้: ผู้รับทั้งหมดไม่ถูกต้อง";
"cannot send message (smtp) - recipients discarded" = "ไม่สามารถส่งข้อความได้ ที่อยู่ต่อไปนี้ไม่ถูกต้อง";
"cannot send message: (smtp) error when connecting" = "ไม่สามารถส่งข้อความ: เกิดข้อผิดพลาดขณะเชื่อมต่อกับเซิร์ฟเวอร์ SMTP";
"cannot sign email without certificate" = "ข้อความไม่สามารถลงลายมือได้เนื่องจากไม่มีใบรับรองที่เกี่ยวข้องกับบัญชีอีเมล";
"cannot sign message because the certificate can't be read" = "ข้อความไม่สามารถลงลายมือได้เนื่องจากไม่สามารถอ่านใบรับรองที่เกี่ยวข้องกับบัญชีอีเมลได้";
"cannot sign message because the certificate doesn't include the specified sender address" = "ข้อความไม่สามารถลงลายมือได้เนื่องจากที่อยู่ผู้ส่งไม่ได้รวมอยู่ในใบรับรองที่เกี่ยวข้องกับบัญชีอีเมล";
/* Contacts list in mail editor */
"Email" = "อีเมล";
"More mail options" = "ตัวเลือกอีเมลเพิ่มเติม";
"Delegation" = "การมอบหมายงาน";
"Add User" = "เพิ่มผู้ใช้";
"Add a tag" = "เพิ่มแท็ก";
"reply" = "ตอบ";
"Edit" = "แก้ไข";
"Yes" = "ใช่";
"No" = "ไม่";
"Location" = "สถานที่";
"Rename" = "เปลี่ยนชื่อ";
"Compact" = "กระชับ";
"Export" = "ส่งออก";
"Set as Drafts" = "ตั้งเป็นแบบร่าง";
"Set as Sent" = "ตั้งเป็นส่งแล้ว";
"Set as Trash" = "ตั้งเป็นอีเมลขยะ";
/* Set the folder as the one holding the Templates */
"Set as Templates" = "ตั้งเป็นเทมเพลต";
/* Set the folder as the one holding Junk mails */
"Set as Junk" = "ตั้งเป็นอีเมลขยะ";
"Sort" = "เรียงลำดับ";
"Order Received" = "เรียงตามผู้รับ";
"Descending Order" = "ลำดับจากมากไปน้อย";
"Back" = "กลับ";
"Copy messages" = "คัดลอกข้อความ";
"More messages options" = "ตัวเลือกข้อความเพิ่มเติม";
"Flag" = "ทำเครื่องหมาย";
"Unflag" = "ยกเลิกเครื่องหมาย";
"Mark as Unread" = "ทำเครื่องหมายว่ายังไม่ได้อ่าน";
"Mark as Read" = "ทำเครื่องหมายว่าอ่านแล้ว";
"Closing Window ..." = "ปิดหน้าต่าง ...";
"Tried to send too many mails. Please wait." = "พยายามส่งอีเมลมากเกินไป โปรดรอสักครู่";
"View Mail" = "ดูเมล์";
"This message contains external images." = "ข้อความนี้มีรูปภาพภายนอก";
"Expanded" = "ขยายขนาด";
"Add a Criteria" = "เพิ่มเกณฑ์";
"More search options" = "ตัวเลือกการค้นหาเพิ่มเติม";
"Your email has been saved" = "อีเมลของคุณถูกบันทึกแล้ว";
"Your email has been sent" = "อีเมลของคุณถูกส่งแล้ว";
"Folder compacted" = "โฟลเดอร์ถูกบีบอัด";
"More Options" = "ตัวเลือกเพิ่มเติม";
"New draft" = "ร่างใหม่";
"Create new draft with this template" = "สร้างร่างใหม่ด้วยเทมเพลตนี้";
/* Advanced search */
"Enter Subject" = "ใส่หัวข้อ";
"Enter From" = "ใส่ผู้ส่ง";
"Enter To" = "ใส่ผู้รับ";
"Enter Cc" = "ใส่สำเนา";
"Enter Body" = "ใส่เนื้อหา";
"match" = "ตรงกัน";
"does not match" = "ไม่ตรงกัน";
/* Aria label for scope of search on messages */
"Search scope" = "ขอบเขตการค้นหา";
/* Subscriptions Dialog */
"Manage Subscriptions" = "จัดการการสมัครสมาชิก";
/* Label of filter input field in subscriptions dialog */
"Filter" = "ตัวกรอง";
/* Hotkey to write a new message */
"hotkey_compose" = "w";
/* Hotkey to flag a message */
"hotkey_flag" = "*";
/* Hotkey to reply to a message */
"hotkey_reply" = "r";
/* Hotkey to reply to all recipients of a message */
"hotkey_replyall" = "a";
/* Hotkey to forward to a message */
"hotkey_forward" = "f";
/* Email deletion */
"Clean folder" = "ล้างโฟลเดอร์";
"Clean mailbox" = "ล้างกล่องอีเมล์";
"Delete permanently (do not use trash)" = "ลบถาวร(อย่าใช้ถังขยะ)";
"Apply to subfolders" = "นำไปใช้กับโฟลเดอร์ย่อย";
"Delete e-mails older than" = "ลบอีเมล์ที่เก่ากว่า";
"3 months" = "3 เดือน";
"6 months" = "6 เดือน";
"9 months" = "9 เดือน";
"1 year" = "1 ปี";
"Custom" = "กำหนดเอง";
"You are about to permanently delete some messages. Are you sure you want to proceed with this action?" = "คุณกำลังจะลบข้อความบางส่วนอย่างถาวร คุณแน่ใจหรือไม่ว่าต้องการดำเนินการ?";
"Apply" = "นำไปใช้";
"%{0} message(s) deleted" = "ลบ %{0} ข้อความแล้ว";
@@ -171,7 +171,7 @@
/* MailListView */
"Sender" = "Gönderici";
"Subject or Sender" = "Konu ya da Gönderici";
"Subject or Recipient" = "Subject or Recipient";
"Subject or Recipient" = "Konu ya da alıcı";
"To or Cc" = "Alıcı veya Kopya";
"Entire Message" = "Tüm ileti";
"Date" = "Tarih";
@@ -517,16 +517,16 @@
"hotkey_forward" = "f";
/* Email deletion */
"Clean folder" = "Clean folder";
"Clean mailbox" = "Clean mailbox";
"Delete permanently (do not use trash)" = "Delete permanently (do not use trash)";
"Apply to subfolders" = "Apply to subfolders";
"Delete e-mails older than" = "Delete e-mails older than";
"3 months" = "3 months";
"6 months" = "6 months";
"9 months" = "9 months";
"1 year" = "1 year";
"Custom" = "Custom";
"You are about to permanently delete some messages. Are you sure you want to proceed with this action?" = "You are about to permanently delete some messages. Are you sure you want to proceed with this action?";
"Apply" = "Apply";
"%{0} message(s) deleted" = "%{0} message(s) deleted";
"Clean folder" = "Klasörü temizle";
"Clean mailbox" = "E-posta kutusunu temizle";
"Delete permanently (do not use trash)" = "Kalıcı olarak sil (çöpe atmadan)";
"Apply to subfolders" = "Alt klasörlere uygula";
"Delete e-mails older than" = "Şundan eski e-postaları sil";
"3 months" = "3 ay";
"6 months" = "6 ay";
"9 months" = "9 ay";
"1 year" = "1 yıl";
"Custom" = "Özel";
"You are about to permanently delete some messages. Are you sure you want to proceed with this action?" = "Bazı iletileri kalıcı olarak silmek üzeresiniz. Bunu yapmak istediğinize emin misiniz?";
"Apply" = "Uygula";
"%{0} message(s) deleted" = "%{0} ileti silindi";
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,6 +73,7 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,6 +73,7 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,6 +73,7 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,6 +73,7 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,6 +73,7 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,6 +73,7 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,6 +73,7 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,6 +73,7 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,6 +73,7 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,6 +73,7 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,6 +73,7 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
+18 -16
View File
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,19 +73,20 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
"About" = "Over";
"AboutBox" = "Developed by Inverse and Alinto, SOGo is a fully-featured groupware server with a focus on scalability and simplicity.<br/><br/>\nSOGo provides a rich AJAX-based Web interface and supports multiple native clients through the use of standard protocols such as CalDAV and CardDAV.<br/><br/>\nSOGo is distributed under the <a href=\"http://gnu.org/licenses/gpl.html\">GNU GPL</a> version 2 or later and parts are distributed under the GNU LGPL version 2. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.<br/><br/>\nSee <a href=\"http://www.sogo.nu/en/support/community.html\">this page</a> for various support options.";
"AboutBox" = "SOGO is een volledig uitgeruste groupware server met focus op schaalbaarheid en eenvoud ontwikkeld door Inverse.<br/><br/>SOGO biedt een rijke AJAX-gebaseerde web-interface en ondersteunt meerdere native clients door gebruik van standaard protocollen als CalDAV en CardDAV.<br/><br/>SOGO wordt gedistribueerd onder de <a href=\"http://gnu.org/licenses/gpl.html\">GNU GPL</a> versie 2 of hoger en onderdelen worden verspreid onder de GNU LGPL versie 2. Dit is vrije software: je bent vrij om het te veranderen en verspreiden. Er is GEEN GARANTIE, voor zover toegestaan ​​door de wet.<br/><br/>Zie <a href=\"http://www.sogo.nu/en/support/community.html\">deze pagina</a> voor diverse support opties.";
"Your account was locked due to too many failed attempts." = "Uw account is geblokkeerd wegens te veel mislukte pogingen.";
"Your account was locked due to an expired password." = "Uw account is geblokkeerd wegens een verlopen wachtwoord.";
"Login failed due to unhandled error case" = "Inloggen mislukt wegens onverwerkte fout";
"Change your Password" = "Verander uw wachtwoord";
"The password was changed successfully." = "Het wachtwoord is met succes veranderd.";
"Your password has expired, please enter a new one below" = "Uw wachtwoord is verlopen, vul hieronder een nieuw wachtwoord in";
"Your password is too weak. Please choose a stronger password to enhance your security" = "Your password is too weak. Please choose a stronger password to enhance your security";
"Your password is too weak. Please choose a stronger password to enhance your security" = "Uw wachtwoord is te zwak. Kies een sterker wachtwoord om uw veiligheid te verbeteren.";
"Password must not be empty." = "Wachtwoord mag niet leeg zijn.";
"The passwords do not match. Please try again." = "De wachtwoorden komen niet overeen. Probeer het opnieuw.";
"Password Grace Period" = "Wachtwoord-respijtperiode";
@@ -114,17 +116,17 @@
"Missing type parameter" = "Ontbrekende typeparameter";
/* Password Recovery */
"Secondary e-mail" = "Secondary e-mail";
"Answer" = "Answer";
"Password lost" = "Password lost";
"No password recovery method has been defined for this user" = "No password recovery method has been defined for this user";
"Invalid secret question answer" = "Invalid secret question answer";
"Next" = "Next";
"Back" = "Back";
"Please enter a new password below" = "Please enter a new password below";
"A link will be sent to %{0}" = "A link will be sent to %{0}";
"A password reset link has been sent, please check your recovery e-mail mailbox and click on the link" = "A password reset link has been sent, please check your recovery e-mail mailbox and click on the link";
"Invalid configuration for email password recovery" = "Invalid configuration for email password recovery";
"Password recovery email in error" = "Password recovery email in error";
"Password reset" = "Password reset";
"Hi %{0},\nThere was a request to change your password!\n\nIf you did not make this request then please ignore this email.\n\nOtherwise, please click this link to change your password: %{1}" = "Hi %{0},\nThere was a request to change your password!\n\nIf you did not make this request then please ignore this email.\n\nOtherwise, please click this link to change your password: %{1}";
"Secondary e-mail" = "Secundair e-mailadres";
"Answer" = "Beantwoord";
"Password lost" = "Wachtwoord verloren";
"No password recovery method has been defined for this user" = "Er is geen wachtwoordherstelmethode gedefinieerd voor deze gebruiker";
"Invalid secret question answer" = "Ongeldig antwoord op geheime vraag";
"Next" = "Volgende";
"Back" = "Terug";
"Please enter a new password below" = "Voer hieronder een nieuw wachtwoord in";
"A link will be sent to %{0}" = "Er wordt een link verzonden naar %{0}";
"A password reset link has been sent, please check your recovery e-mail mailbox and click on the link" = "Er is een link verzonden om uw wachtwoord opnieuw in te stellen. Controleer uw herstel-e-mailbox en klik op de link.";
"Invalid configuration for email password recovery" = "Ongeldige configuratie voor e-mailwachtwoordherstel";
"Password recovery email in error" = "Wachtwoordherstel-e-mail is foutief verzonden";
"Password reset" = "Wachtwoord opnieuw instellen";
"Hi %{0},\nThere was a request to change your password!\n\nIf you did not make this request then please ignore this email.\n\nOtherwise, please click this link to change your password: %{1}" = "Hallo %{0},\nEr is een verzoek ingediend om je wachtwoord te wijzigen!\n\nAls je dit verzoek niet hebt ingediend, negeer dan deze e-mail.\n\nKlik anders op deze link om je wachtwoord te wijzigen: %{1}";
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,6 +73,7 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,6 +73,7 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,6 +73,7 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
+1
View File
@@ -14,6 +14,7 @@ MainUI_OBJC_FILES += \
SOGoUserHomePage.m \
SOGoBrowsersPanel.m \
SOGoMicrosoftActiveSyncActions.m \
SOGoAPIActions.m \
ifeq ($(saml2_config), yes)
MainUI_OBJC_FILES += SOGoSAML2Actions.m
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = " Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,6 +73,7 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,6 +73,7 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,6 +73,7 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,6 +73,7 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,6 +73,7 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,6 +73,7 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,6 +73,7 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,6 +73,7 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,6 +73,7 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
+35
View File
@@ -0,0 +1,35 @@
/* Korean */
{
NSLanguageName = "Korean";
NSFormalName = "한국어";
NSLocaleCode = "ko";
NSLanguageCode = "kor";
NSParentContext = "";
NSAMPMDesignation = ("오전","오후");
NSCurrencySymbol = "₩";
NSDateFormatString = "%A, %B %e, %Y";
NSDateTimeOrdering = MDYH;
NSDecimalDigits = ("0", "1", "2", "3", "4", "5", "6", "7", "8", "9");
NSDecimalSeparator = ".";
NSEarlierTimeDesignations = ("이전", "남은", "이후", "전");
NSHourNameDesignations = ((0, "자정"), (10, "오전"), (12, "정오", "점심"), (14, "오후"), (19, "저녁"));
NSInternationalCurrencyString = KRW;
NSLaterTimeDesignations = ("다음");
NSMonthNameArray = ("1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월");
NSNextDayDesignations = ("내일");
NSNextNextDayDesignations = ("모레");
NSPriorDayDesignations = ("어제");
NSShortDateFormatString = "%m/%e/%y";
NSShortMonthNameArray = (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec);
NSShortTimeDateFormatString = "%m/%e/%y %I:%M %p";
NSShortWeekDayNameArray = ("일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일");
NSThisDayDesignations = ("오늘", "지금");
NSThousandsSeparator = ",";
NSTimeDateFormatString = "%A, %B %e, %Y %I:%M:%S %p %Z";
NSTimeFormatString = "%I:%M:%S %p";
NSWeekDayNameArray = ("일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일");
NSYearMonthWeekDesignations = ("년", "월", "주");
NSPositiveCurrencyFormatString = "₩9,999.00";
NSNegativeCurrencyFormatString = "-₩9,999.00";
}
+132
View File
@@ -0,0 +1,132 @@
/* this file is in UTF-8 format! */
"title" = "SOGo";
"Username" = "사용자 이름";
"Password" = "비밀번호";
"Domain" = "도메인";
"Remember username" = "사용자 이름 기억";
"Connect" = "연결";
/* Appears while authentication is in progress */
"Authenticating" = "인증 중";
/* Appears when authentication succeeds */
"Welcome" = "환영합니다";
"Authentication Failed" = "인증 실패";
"Wrong username or password." = "잘못된 사용자 이름 또는 비밀번호입니다.";
"Retry" = "다시 시도";
"Login failed due to unhandled error case:" = "처리되지 않은 오류로 인해 로그인에 실패했습니다:";
"cookiesNotEnabled" = "브라우저의 쿠키가 비활성화되어 로그인할 수 없습니다. 브라우저 설정에서 쿠키를 활성화하고 다시 시도하십시오.";
"browserNotCompatible" = "현재 브라우저 버전이 이 사이트에서 지원되지 않습니다. Firefox를 사용하시는 것을 권장합니다. 아래 링크를 클릭하여 최신 버전의 브라우저를 다운로드하십시오.";
"alternativeBrowsers" = "또는 다음 호환 브라우저를 사용할 수도 있습니다";
"alternativeBrowserSafari" = "또는 Safari를 사용할 수도 있습니다.";
/* 2FA */
"Verification Code" = "인증 코드";
"Enter the 6-digit verification code from your TOTP application." = "TOTP 애플리케이션에서 6자리 인증 코드를 입력하십시오.";
"You provided an invalid TOTP key." = "유효하지 않은 TOTP 키를 제공했습니다.";
"Two-factor authentication has been disabled. Visit the Preferences module to restore two-factor authentication and reconfigure your TOTP application." = "2단계 인증이 비활성화되었습니다. 환경설정 모듈을 방문하여 2단계 인증을 복원하고 TOTP 애플리케이션을 재구성하십시오.";
"Download" = "다운로드";
"Language" = "언어";
"choose" = "선택...";
"Arabic" = "العربية";
"Basque" = "Euskara";
"Bosnian" = "Bosanski";
"Bulgarian" = "Български";
"Catalan" = "Català";
"ChineseChina" = "简体中文";
"ChineseTaiwan" = "正體中文";
"Croatian" = "Hrvatski";
"Czech" = "Česky";
"Danish" = "Dansk (Danmark)";
"Dutch" = "Nederlands";
"English" = "English";
"Finnish" = "Suomi";
"French" = "Français";
"Galician" = "Galego";
"German" = "Deutsch";
"Hebrew" = "עברית";
"Hungarian" = "Magyar";
"Icelandic" = "Íslenska";
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
"Macedonian" = "Македонски";
"Montenegrin" = "Crnogorski";
"NorwegianBokmal" = "Norsk bokmål";
"NorwegianNynorsk" = "Norsk nynorsk";
"Polish" = "Polski";
"Portuguese" = "Português";
"BrazilianPortuguese" = "Português brasileiro";
"Romanian" = "Română";
"Russian" = "Русский";
"Serbian" = "Српски";
"SerbianLatin" = "Srpski";
"Slovak" = "Slovensky";
"Slovenian" = "Slovenščina";
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
"About" = "정보";
"AboutBox" = "Inverse와 Alinto가 개발한 SOGo는 확장성과 단순성에 중점을 둔 완벽한 그룹웨어 서버입니다.<br/><br/>SOGo는 풍부한 AJAX 기반 웹 인터페이스를 제공하며 CalDAV 및 CardDAV와 같은 표준 프로토콜을 사용하여 여러 기본 클라이언트를 지원합니다.<br/><br/>SOGo는 <a href=\"http://gnu.org/licenses/gpl.html\">GNU GPL</a> 버전 2 이상으로 배포되며, 일부는 GNU LGPL 버전 2로 배포됩니다. 이는 자유 소프트웨어이며, 자유롭게 변경하고 재배포할 수 있습니다. 법이 허용하는 범위 내에서 어떠한 보증도 제공하지 않습니다.<br/><br/>다양한 지원 옵션은 <a href=\"http://www.sogo.nu/en/support/community.html\">이 페이지</a>를 참조하십시오.";
"Your account was locked due to too many failed attempts." = "너무 많은 로그인 시도 실패로 계정이 잠겼습니다.";
"Your account was locked due to an expired password." = "비밀번호 만료로 인해 계정이 잠겼습니다.";
"Login failed due to unhandled error case" = "처리되지 않은 오류로 인해 로그인에 실패했습니다";
"Change your Password" = "비밀번호 변경";
"The password was changed successfully." = "비밀번호가 성공적으로 변경되었습니다.";
"Your password has expired, please enter a new one below" = "비밀번호가 만료되었습니다. 아래에 새 비밀번호를 입력하십시오";
"Your password is too weak. Please choose a stronger password to enhance your security" = "비밀번호가 너무 약합니다. 보안 강화를 위해 더 강력한 비밀번호를 선택하십시오";
"Password must not be empty." = "비밀번호는 비워둘 수 없습니다.";
"The passwords do not match. Please try again." = "비밀번호가 일치하지 않습니다. 다시 시도하십시오.";
"Password Grace Period" = "비밀번호 유예 기간";
"You have %{0} logins remaining before your account is locked. Please change your password in the preference dialog." = "계정이 잠기기 전까지 %{0}번의 로그인이 남았습니다. 환경설정 대화 상자에서 비밀번호를 변경하십시오.";
"Password about to expire" = "비밀번호 만료 예정";
"Your password is going to expire in %{0} %{1}." = "귀하의 비밀번호는 %{0} %{1} 후에 만료됩니다.";
"days" = "일";
"hours" = "시간";
"minutes" = "분";
"seconds" = "초";
"Password change failed" = "비밀번호 변경 실패";
"Password change failed - Permission denied" = "비밀번호 변경 실패 - 권한 거부";
"Password change failed - Insufficient password quality" = "비밀번호 변경 실패 - 불충분한 비밀번호 품질";
"Password change failed - Password is too short" = "비밀번호 변경 실패 - 비밀번호가 너무 짧습니다";
"Password change failed - Password is too young" = "비밀번호 변경 실패 - 비밀번호 사용 기간이 너무 짧습니다";
"Password change failed - Password is in history" = "비밀번호 변경 실패 - 비밀번호가 기록에 있습니다";
"Unhandled policy error: %{0}" = "처리되지 않은 정책 오류: %{0}";
"Unhandled error response" = "처리되지 않은 오류 응답";
"Password change is not supported." = "비밀번호 변경이 지원되지 않습니다.";
"Unhandled HTTP error code: %{0}" = "처리되지 않은 HTTP 오류 코드: %{0}";
"New password" = "새 비밀번호";
"Confirmation" = "확인";
"Cancel" = "취소";
"Please wait..." = "기다려 주십시오...";
"Close" = "닫기";
"Missing search parameter" = "검색 매개변수 누락";
"Missing type parameter" = "유형 매개변수 누락";
/* Password Recovery */
"Secondary e-mail" = "보조 이메일";
"Answer" = "답변";
"Password lost" = "비밀번호 분실";
"No password recovery method has been defined for this user" = "이 사용자에 대해 정의된 비밀번호 복구 방법이 없습니다";
"Invalid secret question answer" = "잘못된 비밀 질문 답변";
"Next" = "다음";
"Back" = "뒤로";
"Please enter a new password below" = "아래에 새 비밀번호를 입력하십시오";
"A link will be sent to %{0}" = "%{0}으로 링크가 전송됩니다";
"A password reset link has been sent, please check your recovery e-mail mailbox and click on the link" = "비밀번호 재설정 링크가 전송되었습니다. 복구 이메일 사서함을 확인하고 링크를 클릭하십시오";
"Invalid configuration for email password recovery" = "비밀번호 복구 이메일에 대한 잘못된 설정";
"Password recovery email in error" = "비밀번호 복구 이메일 오류";
"Password reset" = "비밀번호 재설정";
"Hi %{0},\nThere was a request to change your password!\n\nIf you did not make this request then please ignore this email.\n\nOtherwise, please click this link to change your password: %{1}" = "안녕하세요 %{0}님,\n비밀번호 변경 요청이 있었습니다!\n\n요청하지 않으셨다면 이 이메일을 무시하십시오.\n\n그렇지 않다면, 다음 링크를 클릭하여 비밀번호를 변경하십시오: %{1}";
@@ -53,6 +53,7 @@
"Indonesian" = "bahasa Indonesia";
"Italian" = "Italiano";
"Japanese" = "日本語";
"Korean" = "한국어";
"Kazakh" = "Қазақ";
"Latvian" = "Latviešu";
"Lithuanian" = "Lietuvių";
@@ -72,6 +73,7 @@
"SpanishSpain" = "Español (España)";
"SpanishArgentina" = "Español (Argentina)";
"Swedish" = "Svenska";
"Thai" = "ภาษา";
"TurkishTurkey" = "Türkçe (Türkiye)";
"Ukrainian" = "Українська";
"Welsh" = "Cymraeg";
Loaded 100 of 205 files, more files were not shown because too many files have changed in this diff. Show more