TUIGlobalization.m 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. //
  2. // NSBundle+TUIKIT.m
  3. // Pods
  4. //
  5. // Created by harvy on 2020/10/9.
  6. // Copyright © 2023 Tencent. All rights reserved.
  7. //
  8. #import "TUIGlobalization.h"
  9. #import <objc/runtime.h>
  10. #import "TUIDefine.h"
  11. @implementation TUIGlobalization
  12. + (void)load {
  13. NSString *language = [TUIGlobalization getPreferredLanguage];
  14. if([language hasPrefix:@"ar"]) {
  15. [TUIGlobalization setRTLOption:YES];
  16. }
  17. else {
  18. [TUIGlobalization setRTLOption:NO];
  19. }
  20. }
  21. static NSString *gCustomLanguage = nil;
  22. static BOOL gRTLOption = NO;
  23. + (NSString *)getLocalizedStringForKey:(NSString *)key bundle:(NSString *)bundleName {
  24. return [self getLocalizedStringForKey:key value:nil bundle:bundleName];
  25. }
  26. + (NSString *)getLocalizedStringForKey:(NSString *)key value:(nullable NSString *)value bundle:(nonnull NSString *)bundleName {
  27. static NSMutableDictionary *bundleCache = nil;
  28. if (bundleCache == nil) {
  29. bundleCache = [NSMutableDictionary dictionary];
  30. }
  31. NSString *language = [self getPreferredLanguage];
  32. language = [@"Localizable" stringByAppendingPathComponent:language];
  33. NSString *cacheKey = [NSString stringWithFormat:@"%@_%@", bundleName, language];
  34. NSBundle *bundle = [bundleCache objectForKey:cacheKey];
  35. if (bundle == nil) {
  36. bundle = [NSBundle bundleWithPath:[TUIKitLocalizable(bundleName) pathForResource:language ofType:@"lproj"]];
  37. if (bundle) {
  38. [bundleCache setObject:bundle forKey:cacheKey];
  39. }
  40. }
  41. value = [bundle localizedStringForKey:key value:value table:nil];
  42. // It's not necessary to query at main bundle, cause it's a long-time operation
  43. // NSString *resultStr = [[NSBundle mainBundle] localizedStringForKey:key value:value table:nil];
  44. return value ?: @"";
  45. }
  46. + (NSString *)getPreferredLanguage {
  47. // Custom language in app
  48. if (gCustomLanguage == nil) {
  49. gCustomLanguage = [NSUserDefaults.standardUserDefaults objectForKey:TUICustomLanguageKey];
  50. }
  51. if (gCustomLanguage.length > 0) {
  52. return gCustomLanguage;
  53. }
  54. // Follow system changes by default
  55. NSString *language = [NSLocale preferredLanguages].firstObject;
  56. if ([language hasPrefix:@"en"]) {
  57. language = @"en";
  58. } else if ([language hasPrefix:@"zh"]) {
  59. if ([language rangeOfString:@"Hans"].location != NSNotFound) {
  60. // Simplified Chinese
  61. language = @"zh-Hans";
  62. } else {
  63. // Traditional Chinese
  64. language = @"zh-Hant";
  65. }
  66. } else if ([language hasPrefix:@"ar"]) {
  67. language = @"ar";
  68. }
  69. else {
  70. language = @"en";
  71. }
  72. return language;
  73. }
  74. + (void)setPreferredLanguage:(NSString *)language {
  75. gCustomLanguage = language;
  76. [NSUserDefaults.standardUserDefaults setObject:language ?: @"" forKey:TUICustomLanguageKey];
  77. [NSUserDefaults.standardUserDefaults synchronize];
  78. dispatch_async(dispatch_get_main_queue(), ^{
  79. [NSNotificationCenter.defaultCenter postNotificationName:TUIChangeLanguageNotification object:nil];
  80. });
  81. }
  82. + (void)ignoreTraditionChinese:(BOOL)ignore {
  83. #ifdef DEBUG
  84. NSAssert(false, @"traditional chinese is now supported by the TUIKit component, and the current API has been deprecated");
  85. #endif
  86. }
  87. + (void)setRTLOption:(BOOL)op {
  88. gRTLOption = op;
  89. [UIView appearance].semanticContentAttribute = op?UISemanticContentAttributeForceRightToLeft:UISemanticContentAttributeForceLeftToRight;
  90. [UISearchBar appearance].semanticContentAttribute = op?UISemanticContentAttributeForceRightToLeft:UISemanticContentAttributeForceLeftToRight;
  91. [UICollectionView appearance].semanticContentAttribute = op?UISemanticContentAttributeForceRightToLeft:UISemanticContentAttributeForceLeftToRight;
  92. [UISwitch appearance].semanticContentAttribute = op?UISemanticContentAttributeForceRightToLeft:UISemanticContentAttributeForceLeftToRight;
  93. [NSUserDefaults.standardUserDefaults setBool:op forKey:TUIKitGlobalizationRTLOptionKey];
  94. [NSUserDefaults.standardUserDefaults synchronize];
  95. }
  96. + (BOOL)getRTLOption {
  97. return gRTLOption;
  98. }
  99. #pragma mark - Deprecated
  100. + (NSString *)g_localizedStringForKey:(NSString *)key bundle:(nonnull NSString *)bundleName {
  101. return [self getLocalizedStringForKey:key value:nil bundle:bundleName];
  102. }
  103. + (NSString *)tk_localizableLanguageKey {
  104. return [self getPreferredLanguage];
  105. }
  106. @end
  107. @interface TUIBundle : NSBundle
  108. @end
  109. @implementation TUIBundle
  110. - (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName {
  111. if ([TUIBundle private_mainBundle]) {
  112. return [[TUIBundle private_mainBundle] localizedStringForKey:key value:value table:tableName];
  113. } else {
  114. return [super localizedStringForKey:key value:value table:tableName];
  115. }
  116. }
  117. + (NSBundle *)private_mainBundle {
  118. static NSMutableDictionary *bundleCache;
  119. if (bundleCache == nil) {
  120. bundleCache = [NSMutableDictionary dictionary];
  121. }
  122. NSString *customLanguage = [TUIGlobalization getPreferredLanguage];
  123. if (customLanguage.length) {
  124. NSString *path = [[NSBundle mainBundle] pathForResource:customLanguage ofType:@"lproj"] ?: @"";
  125. NSBundle *bundle = [bundleCache objectForKey:path];
  126. if (bundle == nil) {
  127. bundle = [NSBundle bundleWithPath:path];
  128. if (bundle) {
  129. [bundleCache setObject:bundle forKey:path];
  130. }
  131. }
  132. return bundle;
  133. }
  134. return nil;
  135. }
  136. @end
  137. @interface NSBundle (Localization)
  138. @end
  139. @implementation NSBundle (Localization)
  140. + (void)load {
  141. static dispatch_once_t onceToken;
  142. dispatch_once(&onceToken, ^{
  143. object_setClass([NSBundle mainBundle], [TUIBundle class]);
  144. });
  145. }
  146. @end