ObjFW  Diff

Differences From Artifact [ccac2d9a08]:

To Artifact [e8b5569b76]:


36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
36
37
38
39
40
41
42

43
44
45
46
47
48
49
50







-
+








static OFLocale *currentLocale = nil;
static OFDictionary *operatorPrecedences = nil;

#ifndef OF_AMIGAOS
static void
parseLocale(char *locale, OFStringEncoding *encoding,
    OFString **language, OFString **territory)
    OFString **languageCode, OFString **countryCode)
{
	locale = OFStrDup(locale);

	@try {
		OFStringEncoding enc = OFStringEncodingASCII;
		char *tmp;

61
62
63
64
65
66
67
68

69
70
71
72
73
74




75
76
77
78
79



80
81
82
83
84
85
86
61
62
63
64
65
66
67

68
69
70
71



72
73
74
75
76
77



78
79
80
81
82
83
84
85
86
87







-
+



-
-
-
+
+
+
+


-
-
-
+
+
+







					*encoding = OFStringEncodingParseName(
					    [OFString stringWithCString: tmp
							       encoding: enc]);
			} @catch (OFInvalidArgumentException *e) {
			}
		}

		/* Territory */
		/* Country code */
		if ((tmp = strrchr(locale, '_')) != NULL) {
			*tmp++ = '\0';

			if (territory != NULL)
				*territory = [OFString stringWithCString: tmp
								encoding: enc];
			if (countryCode != NULL)
				*countryCode = [OFString
				    stringWithCString: tmp
					     encoding: enc];
		}

		if (language != NULL)
			*language = [OFString stringWithCString: locale
						       encoding: enc];
		if (languageCode != NULL)
			*languageCode = [OFString stringWithCString: locale
							   encoding: enc];
	} @finally {
		OFFreeMemory(locale);
	}
}
#endif

static bool
299
300
301
302
303
304
305
306
307


308
309
310
311
312
313
314
300
301
302
303
304
305
306


307
308
309
310
311
312
313
314
315







-
-
+
+








	[string makeImmutable];

	return string;
}

@implementation OFLocale
@synthesize language = _language, territory = _territory, encoding = _encoding;
@synthesize decimalPoint = _decimalPoint;
@synthesize languageCode = _languageCode, countryCode = _countryCode;
@synthesize encoding = _encoding, decimalSeparator = _decimalSeparator;

+ (void)initialize
{
	OFNumber *one, *two, *three, *four;

	if (self != [OFLocale class])
		return;
336
337
338
339
340
341
342
343

344
345

346
347
348

349
350

351
352
353
354
355
356
357
358

359
360

361
362
363
364

365
366

367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383

384
385
386
387

388
389
390
391
392
393
394
395
396
397
398
399
400
401

402
403
404


405
406
407
408
409
410
411
337
338
339
340
341
342
343

344
345

346
347
348

349
350

351
352
353
354
355
356
357
358

359
360

361
362
363
364

365
366

367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383

384
385
386
387

388
389
390
391
392
393
394
395
396
397
398
399
400
401

402
403


404
405
406
407
408
409
410
411
412







-
+

-
+


-
+

-
+







-
+

-
+



-
+

-
+
















-
+



-
+













-
+

-
-
+
+







}

+ (OFLocale *)currentLocale
{
	return currentLocale;
}

+ (OFString *)language
+ (OFString *)languageCode
{
	return currentLocale.language;
	return currentLocale.languageCode;
}

+ (OFString *)territory
+ (OFString *)countryCode
{
	return currentLocale.territory;
	return currentLocale.countryCode;
}

+ (OFStringEncoding)encoding
{
	return currentLocale.encoding;
}

+ (OFString *)decimalPoint
+ (OFString *)decimalSeparator
{
	return currentLocale.decimalPoint;
	return currentLocale.decimalSeparator;
}

#ifdef OF_HAVE_FILES
+ (void)addLanguageDirectory: (OFString *)path
+ (void)addLocalizationDirectory: (OFString *)path
{
	[currentLocale addLanguageDirectory: path];
	[currentLocale addLocalizationDirectory: path];
}
#endif

- (instancetype)init
{
	self = [super init];

	@try {
#ifndef OF_AMIGAOS
		char *locale, *messagesLocale = NULL;

		if (currentLocale != nil)
			@throw [OFInitializationFailedException
			    exceptionWithClass: self.class];

		_encoding = OFStringEncodingUTF8;
		_decimalPoint = @".";
		_decimalSeparator = @".";
		_localizedStrings = [[OFMutableArray alloc] init];

		if ((locale = setlocale(LC_ALL, "")) != NULL)
			_decimalPoint = [[OFString alloc]
			_decimalSeparator = [[OFString alloc]
			    initWithCString: localeconv()->decimal_point
				   encoding: _encoding];

# ifdef LC_MESSAGES
		messagesLocale = setlocale(LC_MESSAGES, "");
# endif
		if (messagesLocale == NULL)
			messagesLocale = locale;

		if (messagesLocale != NULL) {
			void *pool = objc_autoreleasePoolPush();

			parseLocale(messagesLocale, &_encoding,
			    &_language, &_territory);
			    &_languageCode, &_countryCode);

			[_language retain];
			[_territory retain];
			[_languageCode retain];
			[_countryCode retain];

			objc_autoreleasePoolPop(pool);
		}
#else
		void *pool = objc_autoreleasePoolPush();
		char buffer[32];
		struct Locale *locale;
435
436
437
438
439
440
441
442

443
444
445
446
447
448
449

450
451
452
453
454
455

456
457
458

459
460
461
462

463
464
465
466


467
468
469
470
471
472
473
436
437
438
439
440
441
442

443
444
445
446
447
448
449

450
451
452
453
454
455

456
457
458

459
460
461
462

463
464
465


466
467
468
469
470
471
472
473
474







-
+






-
+





-
+


-
+



-
+


-
-
+
+







		} else
			_encoding = OFStringEncodingISO8859_1;

		/*
		 * Get it via localeconv() instead of from the Locale struct,
		 * to make sure we and printf etc. have the same expectations.
		 */
		_decimalPoint = [[OFString alloc]
		_decimalSeparator = [[OFString alloc]
		    initWithCString: localeconv()->decimal_point
			   encoding: _encoding];

		_localizedStrings = [[OFMutableArray alloc] init];

		if (GetVar("Language", buffer, sizeof(buffer), 0) > 0)
			_language = [[OFString alloc]
			_languageCode = [[OFString alloc]
			    initWithCString: buffer
				   encoding: _encoding];

		if ((locale = OpenLocale(NULL)) != NULL) {
			@try {
				uint32_t territory;
				uint32_t countryCode;
				size_t length;

				territory =
				countryCode =
				    OFToBigEndian32(locale->loc_CountryCode);

				for (length = 0; length < 4; length++)
					if (((char *)&territory)[length] == 0)
					if (((char *)&countryCode)[length] == 0)
						break;

				_territory = [[OFString alloc]
				    initWithCString: (char *)&territory
				_countryCode = [[OFString alloc]
				    initWithCString: (char *)&countryCode
					   encoding: _encoding
					     length: length];
			} @finally {
				CloseLocale(locale);
			}
		}

481
482
483
484
485
486
487
488
489
490



491
492
493
494
495
496
497

498
499
500

501
502
503

504
505
506
507
508

509
510
511
512
513
514
515
516
517
518


519
520
521


522
523
524
525





526
527

528
529
530
531
532
533


534
535
536

537
538
539
540
541
542
543
482
483
484
485
486
487
488



489
490
491
492
493
494
495
496
497

498
499
500

501
502
503

504
505
506
507
508

509
510
511
512
513
514
515
516
517


518
519
520


521
522
523



524
525
526
527
528
529

530
531
532
533
534


535
536
537
538

539
540
541
542
543
544
545
546







-
-
-
+
+
+






-
+


-
+


-
+




-
+








-
-
+
+

-
-
+
+

-
-
-
+
+
+
+
+

-
+




-
-
+
+


-
+







	currentLocale = self;

	return self;
}

- (void)dealloc
{
	[_language release];
	[_territory release];
	[_decimalPoint release];
	[_languageCode release];
	[_countryCode release];
	[_decimalSeparator release];
	[_localizedStrings release];

	[super dealloc];
}

#ifdef OF_HAVE_FILES
- (void)addLanguageDirectory: (OFString *)path
- (void)addLocalizationDirectory: (OFString *)path
{
	void *pool;
	OFString *mapPath, *language, *territory, *languageFile;
	OFString *mapPath, *languageCode, *countryCode, *localizationFile;
	OFDictionary *map;

	if (_language == nil)
	if (_languageCode == nil)
		return;

	pool = objc_autoreleasePoolPush();

	mapPath = [path stringByAppendingPathComponent: @"languages.json"];
	mapPath = [path stringByAppendingPathComponent: @"localizations.json"];
	@try {
		map = [[OFString stringWithContentsOfFile: mapPath]
		     objectByParsingJSON];
	} @catch (OFOpenItemFailedException *e) {
		objc_autoreleasePoolPop(pool);
		return;
	}

	language = _language.lowercaseString;
	territory = _territory.lowercaseString;
	languageCode = _languageCode.lowercaseString;
	countryCode = _countryCode.lowercaseString;

	if (territory == nil)
		territory = @"";
	if (countryCode == nil)
		countryCode = @"";

	languageFile = [[map objectForKey: language] objectForKey: territory];
	if (languageFile == nil)
		languageFile = [[map objectForKey: language] objectForKey: @""];
	localizationFile = [[map objectForKey: languageCode]
	    objectForKey: countryCode];
	if (localizationFile == nil)
		localizationFile = [[map objectForKey: languageCode]
		    objectForKey: @""];

	if (languageFile == nil) {
	if (localizationFile == nil) {
		objc_autoreleasePoolPop(pool);
		return;
	}

	languageFile = [path stringByAppendingPathComponent:
	    [languageFile stringByAppendingString: @".json"]];
	localizationFile = [path stringByAppendingPathComponent:
	    [localizationFile stringByAppendingString: @".json"]];

	[_localizedStrings addObject: [[OFString stringWithContentsOfFile:
	    languageFile] objectByParsingJSON]];
	    localizationFile] objectByParsingJSON]];

	objc_autoreleasePoolPop(pool);
}
#endif

- (OFString *)localizedStringForID: (OFConstantString *)ID
			  fallback: (id)fallback, ...