Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions MJRefresh/Base/MJRefreshComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ typedef void (^MJRefreshComponentAction)(void);
/** 当scrollView的拖拽状态发生改变的时候调用 */
- (void)scrollViewPanStateDidChange:(nullable NSDictionary *)change NS_REQUIRES_SUPER;

/** 多语言配置 language 发生变化时调用

`MJRefreshConfig.defaultConfig.language` 发生改变时调用.

⚠️ 父类会调用 `placeSubviews` 方法, 请勿在 placeSubviews 中调用本方法, 造成死循环. 子类在需要重新布局时, 在配置完修改后, 最后再调用 super 方法, 否则可能导致配置修改后, 定位先于修改执行.
*/
- (void)i18nDidChange NS_REQUIRES_SUPER;

#pragma mark - 其他
/** 拉拽的百分比(交给子类重写) */
Expand Down
7 changes: 7 additions & 0 deletions MJRefresh/Base/MJRefreshComponent.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#import "MJRefreshComponent.h"
#import "MJRefreshConst.h"
#import "MJRefreshConfig.h"

@interface MJRefreshComponent()
@property (strong, nonatomic) UIPanGestureRecognizer *pan;
Expand Down Expand Up @@ -92,6 +93,8 @@ - (void)addObservers
[self.scrollView addObserver:self forKeyPath:MJRefreshKeyPathContentSize options:options context:nil];
self.pan = self.scrollView.panGestureRecognizer;
[self.pan addObserver:self forKeyPath:MJRefreshKeyPathPanState options:options context:nil];

[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(i18nDidChange) name:MJRefreshDidChangeLanguageNotification object:MJRefreshConfig.defaultConfig];
}

- (void)removeObservers
Expand Down Expand Up @@ -125,6 +128,10 @@ - (void)scrollViewContentOffsetDidChange:(NSDictionary *)change{}
- (void)scrollViewContentSizeDidChange:(NSDictionary *)change{}
- (void)scrollViewPanStateDidChange:(NSDictionary *)change{}

- (void)i18nDidChange {
[self placeSubviews];
}

#pragma mark - 公共方法
#pragma mark 设置回调对象和回调方法
- (void)setRefreshingTarget:(id)target refreshingAction:(SEL)action
Expand Down
19 changes: 15 additions & 4 deletions MJRefresh/Custom/Footer/Auto/MJRefreshAutoStateFooter.m
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ - (void)stateLabelClick
}
}

- (void)textConfiguration {
// 初始化文字
[self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshAutoFooterIdleText] forState:MJRefreshStateIdle];
[self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshAutoFooterRefreshingText] forState:MJRefreshStateRefreshing];
[self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshAutoFooterNoMoreDataText] forState:MJRefreshStateNoMoreData];
}

#pragma mark - 重写父类的方法
- (void)prepare
{
Expand All @@ -60,16 +67,20 @@ - (void)prepare
// 初始化间距
self.labelLeftInset = MJRefreshLabelLeftInset;

// 初始化文字
[self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshAutoFooterIdleText] forState:MJRefreshStateIdle];
[self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshAutoFooterRefreshingText] forState:MJRefreshStateRefreshing];
[self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshAutoFooterNoMoreDataText] forState:MJRefreshStateNoMoreData];
[self textConfiguration];

// 监听label
self.stateLabel.userInteractionEnabled = YES;
[self.stateLabel addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(stateLabelClick)]];
}

- (void)i18nDidChange {
[self textConfiguration];

[super i18nDidChange];
}


- (void)placeSubviews
{
[super placeSubviews];
Expand Down
19 changes: 14 additions & 5 deletions MJRefresh/Custom/Footer/Back/MJRefreshBackStateFooter.m
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,28 @@ - (NSString *)titleForState:(MJRefreshState)state {
return self.stateTitles[@(state)];
}

- (void)textConfiguration {
// 初始化文字
[self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshBackFooterIdleText] forState:MJRefreshStateIdle];
[self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshBackFooterPullingText] forState:MJRefreshStatePulling];
[self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshBackFooterRefreshingText] forState:MJRefreshStateRefreshing];
[self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshBackFooterNoMoreDataText] forState:MJRefreshStateNoMoreData];
}

#pragma mark - 重写父类的方法
- (void)prepare
{
[super prepare];

// 初始化间距
self.labelLeftInset = MJRefreshLabelLeftInset;
[self textConfiguration];
}

- (void)i18nDidChange {
[self textConfiguration];

// 初始化文字
[self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshBackFooterIdleText] forState:MJRefreshStateIdle];
[self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshBackFooterPullingText] forState:MJRefreshStatePulling];
[self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshBackFooterRefreshingText] forState:MJRefreshStateRefreshing];
[self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshBackFooterNoMoreDataText] forState:MJRefreshStateNoMoreData];
[super i18nDidChange];
}

- (void)placeSubviews
Expand Down
19 changes: 15 additions & 4 deletions MJRefresh/Custom/Header/MJRefreshStateHeader.m
Original file line number Diff line number Diff line change
Expand Up @@ -102,18 +102,29 @@ - (void)setLastUpdatedTimeKey:(NSString *)lastUpdatedTimeKey
}
}


- (void)textConfiguration {
// 初始化文字
[self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshHeaderIdleText] forState:MJRefreshStateIdle];
[self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshHeaderPullingText] forState:MJRefreshStatePulling];
[self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshHeaderRefreshingText] forState:MJRefreshStateRefreshing];
self.lastUpdatedTimeKey = MJRefreshHeaderLastUpdatedTimeKey;
}

#pragma mark - 覆盖父类的方法
- (void)prepare
{
[super prepare];

// 初始化间距
self.labelLeftInset = MJRefreshLabelLeftInset;
[self textConfiguration];
}

- (void)i18nDidChange {
[self textConfiguration];

// 初始化文字
[self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshHeaderIdleText] forState:MJRefreshStateIdle];
[self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshHeaderPullingText] forState:MJRefreshStatePulling];
[self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshHeaderRefreshingText] forState:MJRefreshStateRefreshing];
[super i18nDidChange];
}

- (void)placeSubviews
Expand Down
18 changes: 14 additions & 4 deletions MJRefresh/Custom/Trailer/MJRefreshStateTrailer.m
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,26 @@ - (instancetype)setTitle:(NSString *)title forState:(MJRefreshState)state {
return self;
}

#pragma mark - 覆盖父类的方法
- (void)prepare {
[super prepare];

- (void)textConfiguration {
// 初始化文字
[self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshTrailerIdleText] forState:MJRefreshStateIdle];
[self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshTrailerPullingText] forState:MJRefreshStatePulling];
[self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshTrailerPullingText] forState:MJRefreshStateRefreshing];
}

#pragma mark - 覆盖父类的方法
- (void)prepare {
[super prepare];

[self textConfiguration];
}

- (void)i18nDidChange {
[self textConfiguration];

[super i18nDidChange];
}

- (void)setState:(MJRefreshState)state {
MJRefreshCheckState
// 设置状态文字
Expand Down
1 change: 1 addition & 0 deletions MJRefresh/MJRefresh.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@
#import "MJRefreshAutoGifFooter.h"

#import "MJRefreshNormalTrailer.h"
#import "MJRefreshConfig.h"
15 changes: 13 additions & 2 deletions MJRefresh/MJRefreshConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,19 @@ NS_ASSUME_NONNULL_BEGIN
/** 默认使用的语言版本, 默认为 nil. 将随系统的语言自动改变 */
@property (copy, nonatomic, nullable) NSString *languageCode;

/** @return Singleton Config instance */
+ (instancetype)defaultConfig;
/** 默认使用的语言资源文件名, 默认为 nil, 即默认的 Localizable.strings.

- Attention: 文件名不包含后缀.strings
*/
@property (copy, nonatomic, nullable) NSString *i18nFilename;
/** i18n 多语言资源加载自定义 Bundle.

- Attention: 默认为 nil 采用内置逻辑. 这里设置后将忽略内置逻辑的多语言模式, 采用自定义的多语言 bundle
*/
@property (nonatomic, nullable) NSBundle *i18nBundle;

/** Singleton Config instance */
@property (class, nonatomic, readonly) MJRefreshConfig *defaultConfig;

- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
Expand Down
20 changes: 19 additions & 1 deletion MJRefresh/MJRefreshConfig.m
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
//

#import "MJRefreshConfig.h"
#import "MJRefreshConst.h"
#import "NSBundle+MJRefresh.h"

@interface MJRefreshConfig (Bundle)

+ (void)resetLanguageResourceCache;

@end

@implementation MJRefreshConfig

Expand All @@ -19,6 +27,16 @@ + (instancetype)defaultConfig {
return mj_RefreshConfig;
}


- (void)setLanguageCode:(NSString *)languageCode {
if ([languageCode isEqualToString:_languageCode]) {
return;
}

_languageCode = languageCode;
// 重置语言资源
[MJRefreshConfig resetLanguageResourceCache];
[NSNotificationCenter.defaultCenter
postNotificationName:MJRefreshDidChangeLanguageNotification object:self];
}

@end
2 changes: 2 additions & 0 deletions MJRefresh/MJRefreshConst.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ UIKIT_EXTERN NSString *const MJRefreshHeaderLastTimeText;
UIKIT_EXTERN NSString *const MJRefreshHeaderDateTodayText;
UIKIT_EXTERN NSString *const MJRefreshHeaderNoneLastDateText;

UIKIT_EXTERN NSString *const MJRefreshDidChangeLanguageNotification;

// 状态检查
#define MJRefreshCheckState \
MJRefreshState oldState = self.state; \
Expand Down
2 changes: 2 additions & 0 deletions MJRefresh/MJRefreshConst.m
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,5 @@
NSString *const MJRefreshHeaderLastTimeText = @"MJRefreshHeaderLastTimeText";
NSString *const MJRefreshHeaderDateTodayText = @"MJRefreshHeaderDateTodayText";
NSString *const MJRefreshHeaderNoneLastDateText = @"MJRefreshHeaderNoneLastDateText";

NSString *const MJRefreshDidChangeLanguageNotification = @"MJRefreshDidChangeLanguageNotification";
79 changes: 55 additions & 24 deletions MJRefresh/NSBundle+MJRefresh.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
#import "MJRefreshComponent.h"
#import "MJRefreshConfig.h"

static NSBundle *mj_defaultI18nBundle = nil;
static NSBundle *mj_systemI18nBundle = nil;

@implementation NSBundle (MJRefresh)
+ (instancetype)mj_refreshBundle
{
Expand Down Expand Up @@ -45,37 +48,65 @@ + (NSString *)mj_localizedStringForKey:(NSString *)key

+ (NSString *)mj_localizedStringForKey:(NSString *)key value:(NSString *)value
{
static NSBundle *bundle = nil;
if (bundle == nil) {
NSString *table = MJRefreshConfig.defaultConfig.i18nFilename;

// 如果没有缓存, 则走初始化逻辑
if (mj_defaultI18nBundle == nil) {
NSString *language = MJRefreshConfig.defaultConfig.languageCode;
// 如果配置中没有配置语言
if (!language) {
// (iOS获取的语言字符串比较不稳定)目前框架只处理en、zh-Hans、zh-Hant三种情况,其他按照系统默认处理
language = [NSLocale preferredLanguages].firstObject;
}
NSBundle *bundle = MJRefreshConfig.defaultConfig.i18nBundle;
// 首先优先使用公共配置中的 i18nBundle, 如果为空则使用 mainBundle
bundle = bundle ? bundle : NSBundle.mainBundle;
// 按语言选取语言包
NSString *i18nFolderPath = [bundle pathForResource:language ofType:@"lproj"];
mj_defaultI18nBundle = [NSBundle bundleWithPath:i18nFolderPath];
// 检查语言包, 如果没有查找到, 则默认使用 mainBundle
mj_defaultI18nBundle = mj_defaultI18nBundle ? mj_defaultI18nBundle : NSBundle.mainBundle;

if ([language hasPrefix:@"en"]) {
language = @"en";
} else if ([language hasPrefix:@"zh"]) {
if ([language rangeOfString:@"Hans"].location != NSNotFound) {
language = @"zh-Hans"; // 简体中文
} else { // zh-Hant\zh-HK\zh-TW
language = @"zh-Hant"; // 繁體中文
}
} else if ([language hasPrefix:@"ko"]) {
language = @"ko";
} else if ([language hasPrefix:@"ru"]) {
language = @"ru";
} else if ([language hasPrefix:@"uk"]) {
language = @"uk";
} else {
language = @"en";
// 获取 MJRefresh 自有的语言包
if (mj_systemI18nBundle == nil) {
mj_systemI18nBundle = [self mj_defaultI18nBundleWithLanguage:language];
}

// 从MJRefresh.bundle中查找资源
bundle = [NSBundle bundleWithPath:[[NSBundle mj_refreshBundle] pathForResource:language ofType:@"lproj"]];
}
value = [bundle localizedStringForKey:key value:value table:nil];
return [[NSBundle mainBundle] localizedStringForKey:key value:value table:nil];
// 首先在 MJRefresh 内置语言文件中寻找
value = [mj_systemI18nBundle localizedStringForKey:key value:value table:nil];
// 然后在 MainBundle 对应语言文件中寻找
value = [mj_defaultI18nBundle localizedStringForKey:key value:value table:table];
return value;
}

+ (NSBundle *)mj_defaultI18nBundleWithLanguage:(NSString *)language {
if ([language hasPrefix:@"en"]) {
language = @"en";
} else if ([language hasPrefix:@"zh"]) {
if ([language rangeOfString:@"Hans"].location != NSNotFound) {
language = @"zh-Hans"; // 简体中文
} else { // zh-Hant\zh-HK\zh-TW
language = @"zh-Hant"; // 繁體中文
}
} else if ([language hasPrefix:@"ko"]) {
language = @"ko";
} else if ([language hasPrefix:@"ru"]) {
language = @"ru";
} else if ([language hasPrefix:@"uk"]) {
language = @"uk";
} else {
language = @"en";
}

// 从MJRefresh.bundle中查找资源
return [NSBundle bundleWithPath:[[NSBundle mj_refreshBundle] pathForResource:language ofType:@"lproj"]];
}
@end

@implementation MJRefreshConfig (Bundle)

+ (void)resetLanguageResourceCache {
mj_defaultI18nBundle = nil;
mj_systemI18nBundle = nil;
}

@end
Loading