From c5b250236fa662e3da04e442f4414f95d64d9308 Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Tue, 21 Apr 2015 18:26:28 -0700 Subject: [PATCH] New: support of base localization and nib localization --- AppKit/Cib/CPCib.j | 40 +++++++------------ AppKit/Cib/CPCibLoading.j | 30 +++++++++----- AppKit/Cib/_CPCibKeyedUnarchiver.j | 30 ++++++-------- AppKit/Cib/_CPLocalizableString.j | 28 ++++++------- Objective-J/CFBundle.js | 61 +++++++++++++++++------------ Tools/nib2cib/NSLocalizableString.j | 1 + 6 files changed, 93 insertions(+), 97 deletions(-) diff --git a/AppKit/Cib/CPCib.j b/AppKit/Cib/CPCib.j index e693fcb21..f3620bb74 100644 --- a/AppKit/Cib/CPCib.j +++ b/AppKit/Cib/CPCib.j @@ -47,10 +47,11 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey"; @implementation CPCib : CPObject { - CPData _data; - CPBundle _bundle; - BOOL _awakenCustomResources; + BOOL _awakenCustomResources @accessors(property=_awakenCustomResources); + CPBundle _bundle; + CPData _data; + CPString _cibName; id _loadDelegate; } @@ -60,6 +61,8 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey"; if (self) { + _cibName = [aURL lastPathComponent]; + _data = [CPURLConnection sendSynchronousRequest:[CPURLRequest requestWithURL:aURL] returningResponse:nil]; if (!_data) @@ -77,6 +80,8 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey"; if (self) { + _cibName = [aURL lastPathComponent]; + [CPURLConnection connectionWithRequest:[CPURLRequest requestWithURL:aURL] delegate:self]; _awakenCustomResources = YES; @@ -89,16 +94,7 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey"; - (id)initWithCibNamed:(CPString)aName bundle:(CPBundle)aBundle { - if (![aName hasSuffix:@".cib"]) - aName = [aName stringByAppendingString:@".cib"]; - - // If aBundle is nil, use mainBundle, but ONLY for searching for the nib, not for resources later. - self = [self initWithContentsOfURL:[aBundle || [CPBundle mainBundle] pathForResource:aName]]; - - if (self) - _bundle = aBundle; - - return self; + return [self initWithCibNamed:aName bundle:aBundle loadDelegate:nil]; } - (id)initWithCibNamed:(CPString)aName bundle:(CPBundle)aBundle loadDelegate:(id)aLoadDelegate @@ -106,8 +102,10 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey"; if (![aName hasSuffix:@".cib"]) aName = [aName stringByAppendingString:@".cib"]; + var bundle = aBundle || [CPBundle mainBundle]; + // If aBundle is nil, use mainBundle, but ONLY for searching for the nib, not for resources later. - self = [self initWithContentsOfURL:[aBundle || [CPBundle mainBundle] pathForResource:aName] loadDelegate:aLoadDelegate]; + self = [self initWithContentsOfURL:[bundle _cibPathForResource:aName] loadDelegate:aLoadDelegate]; if (self) _bundle = aBundle; @@ -115,16 +113,6 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey"; return self; } -- (void)_setAwakenCustomResources:(BOOL)shouldAwakenCustomResources -{ - _awakenCustomResources = shouldAwakenCustomResources; -} - -- (BOOL)_awakenCustomResources -{ - return _awakenCustomResources; -} - - (BOOL)instantiateCibWithExternalNameTable:(CPDictionary)anExternalNameTable { var bundle = _bundle, @@ -133,7 +121,7 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey"; if (!bundle && owner) bundle = [CPBundle bundleForClass:[owner class]]; - var unarchiver = [[_CPCibKeyedUnarchiver alloc] initForReadingWithData:_data bundle:bundle awakenCustomResources:_awakenCustomResources], + var unarchiver = [[_CPCibKeyedUnarchiver alloc] initForReadingWithData:_data bundle:bundle awakenCustomResources:_awakenCustomResources cibName:_cibName], replacementClasses = [anExternalNameTable objectForKey:CPCibReplacementClasses]; if (replacementClasses) @@ -227,4 +215,4 @@ var CPCibDataFileKey = @"CPCibDataFileKey", [aCoder encodeObject:[_data base64] forKey:CPCibDataFileKey]; } -@end +@end \ No newline at end of file diff --git a/AppKit/Cib/CPCibLoading.j b/AppKit/Cib/CPCibLoading.j index 91ae95ed3..fa5bd6956 100644 --- a/AppKit/Cib/CPCibLoading.j +++ b/AppKit/Cib/CPCibLoading.j @@ -26,7 +26,11 @@ @import "CPCib.j" -var CPCibOwner = @"CPCibOwner"; +var CPCibOwner = @"CPCibOwner", + CPBundleDefaultLanguage = @"CPBundleDefaultLanguage", + CPBundleTypeOfLocalization = @"CPBundleTypeOfLocalization", + CPBundleBaseLocalizationType = @"CPBundleBaseLocalizationType", + CPBundleInterfaceBuilderLocalizationType = @"CPBundleInterfaceBuilderLocalizationType"; @implementation CPObject (CPCibLoading) @@ -45,14 +49,7 @@ var CPCibOwner = @"CPCibOwner"; + (CPCib)loadCibNamed:(CPString)aName owner:(id)anOwner { - if (![aName hasSuffix:@".cib"]) - aName = [aName stringByAppendingString:@".cib"]; - - // Path is based solely on anOwner: - var bundle = anOwner ? [CPBundle bundleForClass:[anOwner class]] : [CPBundle mainBundle], - path = [bundle pathForResource:aName]; - - return [self loadCibFile:path externalNameTable:@{ CPCibOwner: anOwner }]; + return [self loadCibNamed:aName owner:anOwner loadDelegate:nil]; } - (CPCib)loadCibFile:(CPString)aFileName externalNameTable:(CPDictionary)aNameTable @@ -76,7 +73,7 @@ var CPCibOwner = @"CPCibOwner"; // Path is based solely on anOwner: var bundle = anOwner ? [CPBundle bundleForClass:[anOwner class]] : [CPBundle mainBundle], - path = [bundle pathForResource:aName]; + path = [bundle _cibPathForResource:aName]; return [self loadCibFile:path externalNameTable:@{ CPCibOwner: anOwner } loadDelegate:aDelegate]; } @@ -91,6 +88,19 @@ var CPCibOwner = @"CPCibOwner"; externalNameTable:aNameTable]]); } +- (CPString)_cibPathForResource:(CPString)aName +{ + var defaultBundleLanguage = [self objectForInfoDictionaryKey:CPBundleDefaultLanguage], + typeOfLocalization = [self objectForInfoDictionaryKey:CPBundleTypeOfLocalization]; + + if (defaultBundleLanguage && (!typeOfLocalization || typeOfLocalization == CPBundleBaseLocalizationType)) + aName = @"Base.lproj/" + aName; + else if (defaultBundleLanguage && typeOfLocalization == CPBundleInterfaceBuilderLocalizationType) + aName = _bundle.loadedLanguage() + ".lproj/" + aName; + + return [self pathForResource:aName]; +} + @end @implementation _CPCibLoadDelegate : CPObject diff --git a/AppKit/Cib/_CPCibKeyedUnarchiver.j b/AppKit/Cib/_CPCibKeyedUnarchiver.j index bdb88d1a0..e68c63ce2 100644 --- a/AppKit/Cib/_CPCibKeyedUnarchiver.j +++ b/AppKit/Cib/_CPCibKeyedUnarchiver.j @@ -21,16 +21,22 @@ */ @import - +@import @implementation _CPCibKeyedUnarchiver : CPKeyedUnarchiver { - CPBundle _bundle; - BOOL _awakenCustomResources; - CPDictionary _externalObjectsForProxyIdentifiers; + BOOL _awakenCustomResources @accessors(getter=awakenCustomResources); + CPBundle _bundle @accessors(getter=bundle); + CPDictionary _externalObjectsForProxyIdentifiers @accessors(setter=setExternalObjectsForProxyIdentifiers:); + CPString _cibName @accessors(getter=cibName); } - (id)initForReadingWithData:(CPData)data bundle:(CPBundle)aBundle awakenCustomResources:(BOOL)shouldAwakenCustomResources +{ + return [self initForReadingWithData:data bundle:aBundle awakenCustomResources:shouldAwakenCustomResources cibName:@""]; +} + +- (id)initForReadingWithData:(CPData)data bundle:(CPBundle)aBundle awakenCustomResources:(BOOL)shouldAwakenCustomResources cibName:(CPString)aCibName { self = [super initForReadingWithData:data]; @@ -38,6 +44,7 @@ { _bundle = aBundle; _awakenCustomResources = shouldAwakenCustomResources; + _cibName = aCibName; [self setDelegate:self]; } @@ -45,21 +52,6 @@ return self; } -- (CPBundle)bundle -{ - return _bundle; -} - -- (BOOL)awakenCustomResources -{ - return _awakenCustomResources; -} - -- (void)setExternalObjectsForProxyIdentifiers:(CPDictionary)externalObjectsForProxyIdentifiers -{ - _externalObjectsForProxyIdentifiers = externalObjectsForProxyIdentifiers; -} - - (id)externalObjectForProxyIdentifier:(CPString)anIdentifier { return [_externalObjectsForProxyIdentifiers objectForKey:anIdentifier]; diff --git a/AppKit/Cib/_CPLocalizableString.j b/AppKit/Cib/_CPLocalizableString.j index 86e74eb02..dca7608bb 100644 --- a/AppKit/Cib/_CPLocalizableString.j +++ b/AppKit/Cib/_CPLocalizableString.j @@ -21,28 +21,21 @@ */ @import +@import -@implementation _CPLocalizableString : CPString +@implementation _CPLocalizableString : CPObject { - CPString _dev @accessors(property=dev); - CPString _key @accessors(property=key); -} - -- (id)init -{ - if (self = [super init]) - { - - } - - return self; + CPString _dev @accessors(property=dev); + CPString _key @accessors(property=key); + CPString _value @accessors(property=value); } @end var CPLocalizableStringDev = @"CPLocalizableStringDev", - CPLocalizableStringKey = @"CPLocalizableStringKey"; + CPLocalizableStringKey = @"CPLocalizableStringKey", + CPLocalizableStringValue = @"CPLocalizableStringValue"; @implementation _CPLocalizableString (CPCoding) @@ -52,15 +45,18 @@ var CPLocalizableStringDev = @"CPLocalizableStringDev", _dev = [aCoder decodeObjectForKey:CPLocalizableStringDev]; _key = [aCoder decodeObjectForKey:CPLocalizableStringKey]; + _value = [aCoder decodeObjectForKey:CPLocalizableStringValue]; - //TODO: here we should not return self but the string from CPLocalizedStringFromTable - return self; + var tableName = [[aCoder cibName] stringByTrimmingCharactersInSet:[CPCharacterSet characterSetWithCharactersInString:@".cib"]]; + + return [[aCoder bundle] localizedStringForKey:_key value:_value table:tableName]; } - (void)encodeWithCoder:(CPCoder)aCoder { [aCoder encodeObject:_dev forKey:CPLocalizableStringDev]; [aCoder encodeObject:_key forKey:CPLocalizableStringKey]; + [aCoder encodeObject:_value forKey:CPLocalizableStringValue]; } @end \ No newline at end of file diff --git a/Objective-J/CFBundle.js b/Objective-J/CFBundle.js index b5a1aad6b..995b60904 100644 --- a/Objective-J/CFBundle.js +++ b/Objective-J/CFBundle.js @@ -35,6 +35,9 @@ var CFBundlesForURLStrings = { }, CFTotalBytesLoaded = 0, CPApplicationSizeInBytes = 0; +var CPBundleDefaultBrowserLanguage = "CPBundleDefaultBrowserLanguage", + CPBundleDefaultLanguage = "CPBundleDefaultLanguage"; + GLOBAL(CFBundle) = function(/*CFURL|String*/ aURL) { aURL = makeAbsoluteURL(aURL).asDirectoryPathURL(); @@ -61,6 +64,7 @@ GLOBAL(CFBundle) = function(/*CFURL|String*/ aURL) this._eventDispatcher = new EventDispatcher(this); this._localizableStrings = []; + this._loadedLanguage = NULL; } DISPLAY_NAME(CFBundle); @@ -148,11 +152,14 @@ CFBundle.prototype.resourcesDirectoryURL = function() DISPLAY_NAME(CFBundle.prototype.resourcesDirectoryURL); -CFBundle.prototype.resourceURL = function(/*String*/ aResourceName, /*String*/ aType, /*String*/ aSubDirectory) +CFBundle.prototype.resourceURL = function(/*String*/ aResourceName, /*String*/ aType, /*String*/ aSubDirectory, /*String*/ localizationName) { if (aType) aResourceName = aResourceName + "." + aType; + if (localizationName) + aResourceName = localizationName + aResourceName; + if (aSubDirectory) aResourceName = aSubDirectory + "/" + aResourceName; @@ -197,6 +204,11 @@ CFBundle.prototype.infoDictionary = function() DISPLAY_NAME(CFBundle.prototype.infoDictionary); +CFBundle.prototype.loadedLanguage = function() +{ + return this._loadedLanguage; +}; + CFBundle.prototype.valueForInfoDictionaryKey = function(/*String*/ aKey) { return this._infoDictionary.valueForKey(aKey); @@ -321,6 +333,7 @@ CFBundle.prototype.load = function(/*BOOL*/ shouldExecute) if (self === CFBundle.mainBundle() && self.valueForInfoDictionaryKey("CPApplicationSize")) CPApplicationSizeInBytes = self.valueForInfoDictionaryKey("CPApplicationSize").valueForKey("executable") || 0; + loadLanguageForBundle(self); loadExecutableAndResources(self, shouldExecute); } @@ -496,12 +509,12 @@ function loadSpritedImagesForBundle(/*Bundle*/ aBundle, success, failure, progre function loadLocalizableStringsForBundle(/*Bundle*/ aBundle, success, failure, progress) { - var language = getCurrentLanguage(); + var language = aBundle._loadedLanguage; if (!language) return; - var localizableStrings = aBundle.valueForInfoDictionaryKey("CPLocalizableStrings"); + var localizableStrings = aBundle.valueForInfoDictionaryKey("CPBundleLocalizableStrings"); if (!localizableStrings) return; @@ -583,18 +596,29 @@ function loadLocalizableContentForFileInBundle(bundle, contentFile, tableName) } } -function getCurrentLanguage() +function loadLanguageForBundle(aBundle) { + if (aBundle._loadedLanguage) + return; + + var defaultLanguage = aBundle.valueForInfoDictionaryKey(CPBundleDefaultLanguage); + + if (defaultLanguage != CPBundleDefaultBrowserLanguage && defaultLanguage) + { + aBundle._loadedLanguage = defaultLanguage; + return; + } + if (typeof navigator == "undefined") - return null; + return; // userLanguage is an IE only property. var language = (typeof navigator.language !== "undefined") ? navigator.language : navigator.userLanguage; if (!language) - return null; + return; - return language.substring(0, 2); + aBundle._loadedLanguage = language.substring(0, 2); } var CFBundleSpriteSupportListeners = [], @@ -841,34 +865,19 @@ CFBundle.prototype.path = function() return this.bundlePath.apply(this, arguments); }; -CFBundle.prototype.pathForResource = function(aResource) +CFBundle.prototype.pathForResource = function(aResource, aType, aSubDirectory, localizationName) { - return this.resourceURL(aResource).absoluteString(); + return this.resourceURL(aResource, aType, aSubDirectory, localizationName).absoluteString(); }; GLOBAL(CFBundleCopyLocalizedString) = function (/*Bundle*/ bundle, key, value, tableName) { - return CFCopyLocalizedStringWithDefaultValue(key, tableName, bundle, value, null); -} - -GLOBAL(CFBundleCopyLocalizationsForPreferences) = function (locArray, prefArray) -{ - -} - -GLOBAL(CFBundleCopyPreferredLocalizationsFromArray) = function (locArray) -{ - -} - -GLOBAL(CFBundleCopyLocalizationsForURL) = function (url) -{ - + return CFCopyLocalizedStringWithDefaultValue(key, tableName, bundle, value, ""); } GLOBAL(CFBundleCopyBundleLocalizations) = function (/*Bundle*/ aBundle) { - + return [this._loadedLanguage]; } GLOBAL(CFCopyLocalizedString) = function (key, comment) diff --git a/Tools/nib2cib/NSLocalizableString.j b/Tools/nib2cib/NSLocalizableString.j index 37087a899..2b2149f0a 100644 --- a/Tools/nib2cib/NSLocalizableString.j +++ b/Tools/nib2cib/NSLocalizableString.j @@ -32,6 +32,7 @@ { _dev = [aCoder decodeObjectForKey:@"NSDev"]; _key = [aCoder decodeObjectForKey:@"NSKey"]; + _value = [aCoder decodeObjectForKey:@"NS.string"]; } return self;