新增多语言支持,更新 Info.plist 文件以包含葡萄牙语(巴西)、西班牙语、俄语和乌兹别克语。重构 YUMIMacroUitls.h 文件以使用 YMLanguageConfig 进行语言代码管理,优化 XPMineSwitchLanguageVC.m 中的语言切换逻辑,确保动态生成语言选项。新增 YMLanguageConfig 类以管理支持的语言列表及相关功能,提升代码可维护性和用户体验。

This commit is contained in:
edwinQQQ
2025-09-11 19:04:54 +08:00
parent 867f893625
commit ca963cf52b
29 changed files with 12068 additions and 82 deletions

View File

@@ -562,6 +562,7 @@
4CA532C02D5CA4D300B8F59F /* LuckyPackageStatusView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CA532BF2D5CA4D300B8F59F /* LuckyPackageStatusView.m */; };
4CA532C32D5F37DC00B8F59F /* LuckyPackageMessageTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CA532C22D5F37DC00B8F59F /* LuckyPackageMessageTableViewCell.m */; };
4CA5A3342D93D4AB00CE41D6 /* 大.svga in Resources */ = {isa = PBXBuildFile; fileRef = 4CA5A3332D93D4AB00CE41D6 /* 大.svga */; };
4CA7410E2E72B8FC00DB6853 /* YMLanguageConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CA7410D2E72B8FC00DB6853 /* YMLanguageConfig.m */; };
4CACCCE42D9A695000CCB135 /* brove_gift.svga in Resources */ = {isa = PBXBuildFile; fileRef = 4CACCCE32D9A695000CCB135 /* brove_gift.svga */; };
4CAE69C52E69922B00A9FC35 /* mic_cp_lv1.svga in Resources */ = {isa = PBXBuildFile; fileRef = 4CAE69C02E69922B00A9FC35 /* mic_cp_lv1.svga */; };
4CAE69C62E69922B00A9FC35 /* mic_cp_lv2.svga in Resources */ = {isa = PBXBuildFile; fileRef = 4CAE69C12E69922B00A9FC35 /* mic_cp_lv2.svga */; };
@@ -2801,6 +2802,14 @@
4CA532C12D5F37DC00B8F59F /* LuckyPackageMessageTableViewCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LuckyPackageMessageTableViewCell.h; sourceTree = "<group>"; };
4CA532C22D5F37DC00B8F59F /* LuckyPackageMessageTableViewCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LuckyPackageMessageTableViewCell.m; sourceTree = "<group>"; };
4CA5A3332D93D4AB00CE41D6 /* 大.svga */ = {isa = PBXFileReference; lastKnownFileType = file; path = "大.svga"; sourceTree = "<group>"; };
4CA7410C2E72B8FC00DB6853 /* YMLanguageConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YMLanguageConfig.h; sourceTree = "<group>"; };
4CA7410D2E72B8FC00DB6853 /* YMLanguageConfig.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = YMLanguageConfig.m; sourceTree = "<group>"; };
4CA7410F2E72B9E600DB6853 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/InfoPlist.strings; sourceTree = "<group>"; };
4CA741102E72B9E600DB6853 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; };
4CA741112E72BA3700DB6853 /* uz-UZ */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "uz-UZ"; path = "uz-UZ.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
4CA741122E72BA3800DB6853 /* uz-UZ */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "uz-UZ"; path = "uz-UZ.lproj/Localizable.strings"; sourceTree = "<group>"; };
4CA741132E72BA5300DB6853 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; };
4CA741142E72BA5600DB6853 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
4CACCCE32D9A695000CCB135 /* brove_gift.svga */ = {isa = PBXFileReference; lastKnownFileType = file; path = brove_gift.svga; sourceTree = "<group>"; };
4CAE69C02E69922B00A9FC35 /* mic_cp_lv1.svga */ = {isa = PBXFileReference; lastKnownFileType = file; path = mic_cp_lv1.svga; sourceTree = "<group>"; };
4CAE69C12E69922B00A9FC35 /* mic_cp_lv2.svga */ = {isa = PBXFileReference; lastKnownFileType = file; path = mic_cp_lv2.svga; sourceTree = "<group>"; };
@@ -8687,6 +8696,8 @@
E83645A42A40AEF600E0DBE4 /* Bundle */ = {
isa = PBXGroup;
children = (
4CA7410C2E72B8FC00DB6853 /* YMLanguageConfig.h */,
4CA7410D2E72B8FC00DB6853 /* YMLanguageConfig.m */,
E83645A62A40AF5400E0DBE4 /* NSBundle+Localizable.h */,
E83645A72A40AF5400E0DBE4 /* NSBundle+Localizable.m */,
);
@@ -11781,6 +11792,9 @@
ar,
tr,
"pt-BR",
ru,
"uz-UZ",
es,
);
mainGroup = 189DD52026DE255300AB55B1;
productRefGroup = 189DD52A26DE255300AB55B1 /* Products */;
@@ -12279,6 +12293,7 @@
E81C27A226EF23490031E639 /* YUMINNNN.h in Sources */,
E80E900C27E0358900434B90 /* XPRoomTopicAlertView.m in Sources */,
54E82EA52CA693FA00C931D9 /* RoomBoomExplosionView.m in Sources */,
4CA7410E2E72B8FC00DB6853 /* YMLanguageConfig.m in Sources */,
9BDA3E7A27FD43EF00517FE6 /* XPAnchorFansTeamEntranceView.m in Sources */,
E81C279826EB3AC40031E639 /* LoginForgetPasswordProtocol.h in Sources */,
9BD8D4E328911E9900AE03FF /* XPMineCollectRoomListViewController.m in Sources */,
@@ -13549,6 +13564,9 @@
2368ECD22BC38FC500EDF4C9 /* zh-Hant */,
54435F2C2CC89D4600F4884B /* tr */,
4C4DE6442E2513DA00122763 /* pt-BR */,
4CA7410F2E72B9E600DB6853 /* ru */,
4CA741112E72BA3700DB6853 /* uz-UZ */,
4CA741132E72BA5300DB6853 /* es */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
@@ -13570,6 +13588,9 @@
2368ECCA2BC38F6F00EDF4C9 /* en */,
54435F2D2CC89D4600F4884B /* tr */,
4C4DE6452E2513DB00122763 /* pt-BR */,
4CA741102E72B9E600DB6853 /* ru */,
4CA741122E72BA3800DB6853 /* uz-UZ */,
4CA741142E72BA5600DB6853 /* es */,
);
name = Localizable.strings;
sourceTree = "<group>";

View File

@@ -5,11 +5,14 @@
// Created by YUMI on 2021/9/10.
//
///一些宏
#import "NSBundle+Localizable.h"
#import <Foundation/Foundation.h>
#import "../Tools/Bundle/NSBundle+Localizable.h"
#ifndef YUMIMacroUitls_h
#define YUMIMacroUitls_h
#import "../Tools/Bundle/YMLanguageConfig.h"
//iPhoneX系列设备(刘海屏设备)
#define iPhoneXSeries \
({BOOL isPhoneXSeries = NO;\
@@ -61,7 +64,7 @@ isPhoneXSeries = [[UIApplication sharedApplication] delegate].window.safeAreaIns
#define YMLocalizedString(key) \
[NSBundle ymLocalizedStringForKey:(key)]
#define isMSRTL() [[NSBundle getLanguageText] hasPrefix:@"ar"]
#define isMSRTL() [YMLanguageConfig isRTLanguage:[NSBundle getLanguageText]]
///是否是中文
#define isMSZH() [[NSBundle getLanguageText] hasPrefix:@"zh"]
///是否是英文
@@ -70,6 +73,12 @@ isPhoneXSeries = [[UIApplication sharedApplication] delegate].window.safeAreaIns
#define isMSTR() [[NSBundle getLanguageText] hasPrefix:@"tr"]
///是否葡萄牙语
#define isMSPT() [[NSBundle getLanguageText] hasPrefix:@"pt"]
///是否西班牙语
#define isMSES() [[NSBundle getLanguageText] hasPrefix:@"es"]
///是否俄语
#define isMSRU() [[NSBundle getLanguageText] hasPrefix:@"ru"]
///是否乌兹别克语
#define isMSUZ() [[NSBundle getLanguageText] hasPrefix:@"uz"]
#endif /* YUMIMacroUitls_h */

View File

@@ -18,6 +18,10 @@
<string>tr</string>
<string>zh</string>
<string>ar</string>
<string>pt-BR</string>
<string>es</string>
<string>ru</string>
<string>uz</string>
</array>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>

View File

@@ -7,8 +7,8 @@
#import "XPMineSwitchLanguageVC.h"
#import "XPMineSettingItemModel.h"
#import "XPMineSwitchLanguageCell.h"
#import "YMLanguageConfig.h"
@interface XPMineSwitchLanguageVC ()<UITableViewDelegate, UITableViewDataSource>
@property(nonatomic,strong) UIButton *saveBtn;
@property (nonatomic,strong) UITableView *tableView;
@@ -34,23 +34,15 @@
[self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(kGetScaleWidth(20));
make.leading.trailing.equalTo(self.view).inset(kGetScaleWidth(16));
make.height.mas_equalTo(kGetScaleWidth(51 * 5));
make.height.mas_equalTo(kGetScaleWidth(51 * [YMLanguageConfig supportedLanguages].count));
}];
}
-(void)saveBtnAction{
NSString *language ;
if ([self.chooseModel.title isEqualToString:@"English"]){
language = @"en";
} else if ([self.chooseModel.title isEqualToString:@"Português (Brasil)"]){
language = @"pt-BR";
} else if ([self.chooseModel.title isEqualToString:@"繁體中文"]){
language = @"zh-Hant";
} else if ([self.chooseModel.title isEqualToString:@"Türkçe"]) {
language = @"tr";
} else{
language = @"ar";
}
if ([language isEqualToString:@"ar"]) {
//
NSString *language = [self languageCodeForDisplayName:self.chooseModel.title];
// RTL
if ([YMLanguageConfig isRTLanguage:language]) {
[UIView appearance].semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;
[UISearchBar appearance].semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;
} else {
@@ -68,6 +60,16 @@
[[NSNotificationCenter defaultCenter] postNotificationName:@"kSwitchLanguage" object:language];
});
}
//
- (NSString *)languageCodeForDisplayName:(NSString *)displayName {
for (NSDictionary *language in [YMLanguageConfig supportedLanguages]) {
if ([language[@"displayName"] isEqualToString:displayName]) {
return language[@"code"];
}
}
return [YMLanguageConfig defaultLanguage];
}
#pragma mark - UITableViewDelegate And UITableViewDataSource
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return kGetScaleWidth(51);
@@ -99,35 +101,23 @@
#pragma mark -
- (NSArray<XPMineSettingItemModel *> *)datasource{
if(!_datasource){
XPMineSettingItemModel *enItem = [XPMineSettingItemModel new];
enItem.title = @"English";
XPMineSettingItemModel *ptBRItem = [XPMineSettingItemModel new];
ptBRItem.title = @"Português (Brasil)";
XPMineSettingItemModel *zhItem = [XPMineSettingItemModel new];
zhItem.title = @"繁體中文";
XPMineSettingItemModel *arItem = [XPMineSettingItemModel new];
arItem.title = @"العربية";
XPMineSettingItemModel *trItem = [XPMineSettingItemModel new];
trItem.title = @"Türkçe";
NSString *language = [NSBundle getLanguageText];
if ([language isEqualToString:@"en"]){
enItem.isChoose = YES;
self.chooseModel = enItem;
}else if ([language isEqualToString:@"pt-BR"]){
ptBRItem.isChoose = YES;
self.chooseModel = ptBRItem;
}else if ([language isEqualToString:@"ar"]){
arItem.isChoose = YES;
self.chooseModel = arItem;
}else if ([language isEqualToString:@"tr"]){
trItem.isChoose = YES;
self.chooseModel = trItem;
}else{
zhItem.isChoose = YES;
self.chooseModel = zhItem;
NSMutableArray<XPMineSettingItemModel *> *items = [NSMutableArray array];
NSString *currentLanguage = [NSBundle getLanguageText];
//
for (NSDictionary *languageConfig in [YMLanguageConfig supportedLanguages]) {
XPMineSettingItemModel *item = [XPMineSettingItemModel new];
item.title = languageConfig[@"displayName"];
item.isChoose = [languageConfig[@"code"] isEqualToString:currentLanguage];
if (item.isChoose) {
self.chooseModel = item;
}
[items addObject:item];
}
_datasource = @[enItem, ptBRItem, zhItem, arItem, trItem];
_datasource = [items copy];
}
return _datasource;
}

View File

@@ -317,7 +317,8 @@ static NSString * const kHomeLayoutTypeKey = @"kHomeLayoutTypeKey";
if ([item isKindOfClass:[XPBlankRoomModel class]]) {
XPPartyRoomItemCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:[XPPartyRoomItemCollectionViewCell blankCellID]
forIndexPath:indexPath];
cell.alpha = 0.1;
cell.alpha = 0.0;
cell.contentView.hidden = YES;
return cell;
}

View File

@@ -12,7 +12,7 @@
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSInteger, RoomType) {
RoomType_Game = 3,
RoomType_Room = 3,
RoomType_Anchor = 6, // 个播房
RoomType_MiniGame = 7,//小游戏房
RoomType_10Mic = 8,//10 个麦位

View File

@@ -1629,7 +1629,7 @@
[params setObject:[NSString stringWithFormat:@"%ld", roomInfo.tagId] forKey:@"tagId"];
}
if ([itemInfo.mgId isEqualToString:@"0"]) {
[params setObject:@(RoomType_Game) forKey:@"type"];
[params setObject:@(RoomType_Room) forKey:@"type"];
[params setObject:@"0" forKey:@"mgId"];
} else {
[params setObject:@(RoomType_MiniGame) forKey:@"type"];

View File

@@ -80,6 +80,7 @@
if (data) {
RedEnvelopeListVo *vo = [RedEnvelopeListVo modelWithJSON:data];
if (vo.roomUid != self.roomUid.integerValue) {
// TODO:
return;
}

View File

@@ -78,6 +78,7 @@
- (UIImageView *)bgImageView {
if (!_bgImageView) {
_bgImageView = [[UIImageView alloc] init];
_bgImageView.contentMode = UIViewContentModeScaleAspectFit;
}
return _bgImageView;
}

View File

@@ -266,7 +266,7 @@
[params setObject:[NSString stringWithFormat:@"%ld", roomInfo.tagId] forKey:@"tagId"];
}
if ([model.mgId isEqualToString:@"0"]) {
[params setObject:@(RoomType_Game) forKey:@"type"];
[params setObject:@(RoomType_Room) forKey:@"type"];
[params setObject:@"0" forKey:@"mgId"];
} else {
[params setObject:@(RoomType_MiniGame) forKey:@"type"];

View File

@@ -1482,6 +1482,10 @@ NSString * const kRoomShowTopicKey = @"kRoomShowTopicKey";
if (model.rowHeight <= 0) {
[self calculateRowHeightForModel:model];
}
if (model.first == CustomMessageType_RedPacket && model.second == Custom_Message_Sub_LuckyPackage) {
return model.rowHeight;
}
return model.rowHeight + 20;
}

View File

@@ -460,7 +460,7 @@
NSInteger row = 0;
switch (type) {
case RoomType_Game:
case RoomType_Room:
row = 0;
break;
case RoomType_10Mic:
@@ -538,10 +538,10 @@
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
if (_updateSelectedType) {
RoomType selectedType = RoomType_Game;
RoomType selectedType = RoomType_Room;
switch (indexPath.row) {
case 0:
selectedType = RoomType_Game;
selectedType = RoomType_Room;
break;
case 1:
selectedType = RoomType_10Mic;

View File

@@ -249,7 +249,7 @@ static CGFloat const kNormalHeight = 160.0f;
NSMutableArray *dataItems = @[].mutableCopy;
switch (self.currentRoomType) {
case RoomType_Game:
case RoomType_Room:
case RoomType_10Mic:
case RoomType_15Mic:
if (iPhoneXSeries) {
@@ -381,6 +381,7 @@ static CGFloat const kNormalHeight = 160.0f;
@kStrongify(self);
self.luckyPackageModel = model;
[self.giftEntranceButton updateEntrance:model];
[self loadLuckyPackage];
}];
[[LuckyPackageLogicManager sharedInstance] registerLuckyPackageUpdate:^(RoomLuckyPackageInfoModel * _Nullable model) {

View File

@@ -30,6 +30,8 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, strong, readonly) NSDictionary<NSNumber *, NSNumber *> *micPositionToUid;
/// CP麦位开关状态
@property (nonatomic, assign) BOOL cpMicEnabled;
/// 房间类型用于判断是否显示CP动画小游戏房不显示
@property (nonatomic, assign) NSInteger roomType;
/// 初始化方法
- (instancetype)initWithContainerView:(UIView *)containerView;

View File

@@ -12,6 +12,7 @@
#import <UIKit/UIKit.h>
#import "XPTurboModeConstants.h"
#import <Foundation/Foundation.h>
#import "RoomInfoModel.h"
@class SVGAImageView;
@class SVGAParser;
@@ -38,6 +39,7 @@
_micPositionToUidInternal = [NSMutableDictionary dictionary];
_midpointRectInfo = [NSMutableDictionary dictionary];
_cpMicEnabled = YES; //
_roomType = 0; //
//
[self setupNotifications];
@@ -67,8 +69,8 @@
[self.containerView addSubview:rectView];
[self.midpointRects addObject:rectView];
// SVGACP
if (autoPlaySVGA && self.cpMicEnabled) {
// SVGACP
if (autoPlaySVGA && self.cpMicEnabled && self.roomType != 7) { // 7 = RoomType_MiniGame
[self playSVGAAnimationAtFrame:frame];
}
@@ -97,8 +99,8 @@
if (leftUid <= 0 && rightUid <= 0) {
return;
}
// SVGACP
if (self.cpMicEnabled) {
// SVGACP
if (self.cpMicEnabled && self.roomType != 7) { // 7 = RoomType_MiniGame
for (MicCpInfoModel *obj in cpList) {
BOOL match = (obj.uid == leftUid && obj.loverUid == rightUid) || (obj.uid == rightUid && obj.loverUid == leftUid);
if (match) {
@@ -324,6 +326,11 @@
return;
}
if (self.roomType == 7) { // 7 = RoomType_MiniGame
NSLog(@"🔧 恢复CP动画当前为小游戏房跳过恢复");
return;
}
if (self.midpointRectInfo.count == 0) {
NSLog(@"🔧 恢复CP动画没有中点矩形信息跳过恢复");
return;

View File

@@ -32,7 +32,7 @@
- (instancetype)init {
self = [super init];
if (self) {
_currentRoomType = RoomType_Game; // RoomType_Game
_currentRoomType = RoomType_Room; // RoomType_Game
}
return self;
}
@@ -127,7 +127,7 @@
self.currentStageView = [[TenMicStageView alloc] initWithDelegate:delegate];
break;
}
case RoomType_Game: // RoomType_Game
case RoomType_Room: // RoomType_Game
default: {
self.currentStageView = [[SocialStageView alloc] initWithDelegate:delegate];
break;

View File

@@ -217,7 +217,7 @@
}
}
MicroQueueModel * micModel = [micQueue objectForKey:[NSString stringWithFormat:@"%d", i - 1]];
if ((micModel && micModel.userInfo && micModel.userInfo.uid > 0) || (micModel.microState.position == -1 && roomInfo.type == RoomType_Game)) {
if ((micModel && micModel.userInfo && micModel.userInfo.uid > 0) || (micModel.microState.position == -1 && roomInfo.type == RoomType_Room)) {
item.isEnable = NO;
item.imageName = @"room_user_position_used";
} else {

View File

@@ -1196,7 +1196,7 @@
case RoomType_MiniGame:
micCount = self.cardInfo.roomInfo.mgMicNum;
break;
case RoomType_Game:
case RoomType_Room:
micCount = 9;
break;
case RoomType_10Mic:

View File

@@ -173,7 +173,7 @@
- (void)handleSelectMode:(NSInteger)type {
switch (type) {
case 1: {
self.selectType = RoomType_Game;
self.selectType = RoomType_Room;
self.selectedExampleImageView.image = [UIImage imageNamed:@"room_type_example_9"];
[self.selectionImageView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(self.bottomArea).offset(16);

View File

@@ -1269,7 +1269,7 @@ XPCandyTreeInsufficientBalanceViewDelegate>
}
if (self.roomInfo.oldType == 0) {
self.roomInfo.oldType = RoomType_Game;
self.roomInfo.oldType = RoomType_Room;
}
[params setObject:@(self.roomInfo.oldType) forKey:@"type"];
[params setObject:@"0" forKey:@"mgId"];
@@ -1631,7 +1631,7 @@ XPCandyTreeInsufficientBalanceViewDelegate>
mgId:self.mgId];
} else { //
NSString* title = [NSString stringWithFormat:YMLocalizedString(@"XPRoomViewController1"), self.userInfo.nick];
RoomType type = RoomType_Game;
RoomType type = RoomType_Room;
if (self.mgId.length > 0) {
type = RoomType_MiniGame;
}
@@ -1712,7 +1712,7 @@ XPCandyTreeInsufficientBalanceViewDelegate>
[XNDJTDDLoadingTool hideHUDInView:self.navigationController.view];
self.roomInfo = roomInfo;
[XPSkillCardPlayerManager shareInstance].is9Mic = roomInfo.type == RoomType_Game;
[XPSkillCardPlayerManager shareInstance].is9Mic = roomInfo.type == RoomType_Room;
if (roomInfo.type == RoomType_Anchor) {
[self handleInitAnchorRoom];
@@ -1970,7 +1970,7 @@ XPCandyTreeInsufficientBalanceViewDelegate>
[self.presenter openRoom:self.roomInfo.title type:self.roomInfo.type roomPwd:self.roomInfo.roomPwd roomDesc:self.roomInfo.roomDesc backPic:@"" mgId:self.mgId];
} else { //
NSString* title = [NSString stringWithFormat:YMLocalizedString(@"XPRoomViewController6"), self.userInfo.nick];
RoomType type = RoomType_Game;
RoomType type = RoomType_Room;
if (self.mgId.length > 0) {
type = RoomType_MiniGame;
}
@@ -3647,6 +3647,10 @@ XPCandyTreeInsufficientBalanceViewDelegate>
if ([manager respondsToSelector:@selector(removeAllMidpointRects)]) {
[manager removeAllMidpointRects];
}
//
if ([manager respondsToSelector:@selector(setRoomType:)]) {
[manager setRoomType:self.roomInfo.type];
}
} else {
//
NSArray<UIView *> *subviews = [self.stageView.subviews copy];
@@ -3783,7 +3787,7 @@ XPCandyTreeInsufficientBalanceViewDelegate>
//
NSInteger maxMicCount = 0;
switch (self.roomInfo.type) {
case RoomType_Game:
case RoomType_Room:
maxMicCount = 9;
break;
case RoomType_10Mic:
@@ -3858,6 +3862,9 @@ XPCandyTreeInsufficientBalanceViewDelegate>
return;
}
//
midpointRectManager.roomType = self.roomInfo.type;
NSInteger userUid = userInfo.uid;
NSArray<NSNumber *> *userUids = @[@(userUid)];
@@ -3902,6 +3909,8 @@ XPCandyTreeInsufficientBalanceViewDelegate>
MicMidpointRectManager *midpointRectManager = (MicMidpointRectManager *)[self.stageView performSelector:@selector(midpointRectManager)];
if (midpointRectManager) {
//
midpointRectManager.roomType = self.roomInfo.type;
//
[midpointRectManager removeCpEntriesForUids:removedUids];
// UI
@@ -3928,7 +3937,7 @@ XPCandyTreeInsufficientBalanceViewDelegate>
NSInteger micCount = 0;
if (self.roomInfo) {
switch (self.roomInfo.type) {
case RoomType_Game: micCount = 9; break;
case RoomType_Room: micCount = 9; break;
case RoomType_10Mic: micCount = 10; break;
case RoomType_15Mic: micCount = 15; break;
case RoomType_19Mic: micCount = 19; break;
@@ -3939,6 +3948,9 @@ XPCandyTreeInsufficientBalanceViewDelegate>
MicMidpointRectManager *midpointRectManager = (MicMidpointRectManager *)[self.stageView performSelector:@selector(midpointRectManager)];
if (midpointRectManager) {
//
midpointRectManager.roomType = self.roomInfo.type;
// CP
// 1. SVGA
[midpointRectManager removeAllMidpointRects];
@@ -3970,7 +3982,7 @@ XPCandyTreeInsufficientBalanceViewDelegate>
NSInteger micCount = 0;
if (self.roomInfo) {
switch (self.roomInfo.type) {
case RoomType_Game: micCount = 9; break;
case RoomType_Room: micCount = 9; break;
case RoomType_10Mic: micCount = 10; break;
case RoomType_15Mic: micCount = 15; break;
case RoomType_19Mic: micCount = 19; break;
@@ -3983,6 +3995,8 @@ XPCandyTreeInsufficientBalanceViewDelegate>
// MicMidpointRectManager *midpointRectManager = [self.stageView midpointRectManager];
MicMidpointRectManager *midpointRectManager = (MicMidpointRectManager *)[self.stageView performSelector:@selector(midpointRectManager)];
if (midpointRectManager) {
//
midpointRectManager.roomType = self.roomInfo.type;
NSDictionary<NSString *, NSArray<NSNumber *> *> *micChanges =
[midpointRectManager diffMicChangeWithStageView:self.stageView micCount:micCount];
@@ -4228,6 +4242,8 @@ XPCandyTreeInsufficientBalanceViewDelegate>
MicMidpointRectManager *midpointRectManager = (MicMidpointRectManager *)[self.stageView performSelector:@selector(midpointRectManager)];
if (midpointRectManager) {
//
midpointRectManager.roomType = self.roomInfo.type;
// UID
NSMutableDictionary<NSString *,MicroQueueModel *> *currentQueue = [self.stageView getMicroQueue];
NSArray<NSString *> *micUserUids = [self getAllMicUserUidsWithQueue:currentQueue];
@@ -4257,7 +4273,7 @@ XPCandyTreeInsufficientBalanceViewDelegate>
NSInteger micCount = 0;
if (self.roomInfo) {
switch (self.roomInfo.type) {
case RoomType_Game: micCount = 9; break;
case RoomType_Room: micCount = 9; break;
case RoomType_10Mic: micCount = 10; break;
case RoomType_15Mic: micCount = 15; break;
case RoomType_19Mic: micCount = 19; break;
@@ -4268,6 +4284,8 @@ XPCandyTreeInsufficientBalanceViewDelegate>
MicMidpointRectManager *midpointRectManager = (MicMidpointRectManager *)[self.stageView performSelector:@selector(midpointRectManager)];
if (midpointRectManager) {
//
midpointRectManager.roomType = self.roomInfo.type;
[midpointRectManager rebuildMicSnapshotWithStageView:self.stageView micCount:micCount];
NSLog(@"🔧 更新麦位快照完成:麦位总数 %ld", (long)micCount);
}

View File

@@ -6,6 +6,7 @@
//
#import "NSBundle+Localizable.h"
#import "YMLanguageConfig.h"
#import <objc/runtime.h>
// key
@@ -20,7 +21,7 @@ static NSString * const kResourceType = @"lproj";
method_exchangeImplementations(oldMethod, newMethod);
}
+ (NSString *)ms_localizedStringForKey:(NSString *)key{
return YMLocalizedString(key);
return [self ymLocalizedStringForKey:key];
}
+(NSString *)ymLocalizedStringForKey:(NSString *)key
{
@@ -63,19 +64,33 @@ static NSString * const kResourceType = @"lproj";
[[NSUserDefaults standardUserDefaults]synchronize];
}
//
// - 使
+ (NSString *)mapLanguageForLocalization:(NSString *)language {
if ([language hasPrefix:@"zh"]) {
return @"zh-Hant"; //
} else if ([language hasPrefix:@"ar"]) {
return @"ar"; //
} else if ([language hasPrefix:@"tr"]) {
return @"tr"; //
} else if ([language hasPrefix:@"pt-BR"] || [language hasPrefix:@"pt"]) {
return @"pt-BR"; // -西
} else {
return @"en"; //
//
for (NSDictionary *langConfig in [YMLanguageConfig supportedLanguages]) {
NSString *code = langConfig[@"code"];
NSString *localizationCode = langConfig[@"localizationCode"];
if ([language isEqualToString:code] || [language isEqualToString:localizationCode]) {
return localizationCode;
}
}
//
for (NSDictionary *langConfig in [YMLanguageConfig supportedLanguages]) {
NSString *code = langConfig[@"code"];
if ([language hasPrefix:code]) {
return langConfig[@"localizationCode"];
}
}
// pt-BR pt
if ([language hasPrefix:@"pt"]) {
return @"pt-BR";
}
//
return [YMLanguageConfig defaultLanguage];
}
@end

View File

@@ -0,0 +1,31 @@
//
// YMLanguageConfig.h
// YuMi
//
// Created by Linus on 2024/12/19.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface YMLanguageConfig : NSObject
/// 支持的语言列表
+ (NSArray<NSDictionary *> *)supportedLanguages;
/// 根据语言代码获取显示名称
+ (NSString *)displayNameForLanguageCode:(NSString *)languageCode;
/// 根据语言代码获取本地化代码
+ (NSString *)localizationCodeForLanguageCode:(NSString *)languageCode;
/// 检查是否为RTL语言
+ (BOOL)isRTLanguage:(NSString *)languageCode;
/// 获取默认语言
+ (NSString *)defaultLanguage;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,61 @@
//
// YMLanguageConfig.m
// YuMi
//
// Created by Linus on 2024/12/19.
//
#import "YMLanguageConfig.h"
@implementation YMLanguageConfig
+ (NSArray<NSDictionary *> *)supportedLanguages {
static NSArray<NSDictionary *> *languages = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
languages = @[
@{@"code": @"en", @"localizationCode": @"en", @"displayName": @"English", @"isRTL": @NO},
@{@"code": @"zh-Hant", @"localizationCode": @"zh-Hant", @"displayName": @"繁體中文", @"isRTL": @NO},
@{@"code": @"ar", @"localizationCode": @"ar", @"displayName": @"العربية", @"isRTL": @YES},
@{@"code": @"tr", @"localizationCode": @"tr", @"displayName": @"Türkçe", @"isRTL": @NO},
@{@"code": @"pt", @"localizationCode": @"pt-BR", @"displayName": @"Português (Brasil)", @"isRTL": @NO},
@{@"code": @"es", @"localizationCode": @"es", @"displayName": @"Español", @"isRTL": @NO},
@{@"code": @"ru", @"localizationCode": @"ru", @"displayName": @"Русский", @"isRTL": @NO},
@{@"code": @"uz", @"localizationCode": @"uz", @"displayName": @"O'zbek", @"isRTL": @NO}
];
});
return languages;
}
+ (NSString *)displayNameForLanguageCode:(NSString *)languageCode {
for (NSDictionary *language in [self supportedLanguages]) {
if ([language[@"code"] isEqualToString:languageCode]) {
return language[@"displayName"];
}
}
return @"English"; //
}
+ (NSString *)localizationCodeForLanguageCode:(NSString *)languageCode {
for (NSDictionary *language in [self supportedLanguages]) {
if ([language[@"code"] isEqualToString:languageCode]) {
return language[@"localizationCode"];
}
}
return @"en"; //
}
+ (BOOL)isRTLanguage:(NSString *)languageCode {
for (NSDictionary *language in [self supportedLanguages]) {
if ([language[@"code"] isEqualToString:languageCode]) {
return [language[@"isRTL"] boolValue];
}
}
return NO;
}
+ (NSString *)defaultLanguage {
return @"en";
}
@end

View File

@@ -0,0 +1,9 @@
NSCameraUsageDescription = "\"Molistar\" necesita su consentimiento antes de que pueda visitar, tomar fotos y subir sus fotos, y luego mostrarlas en su página de inicio personal para que otros lo vean";
NSLocalNetworkUsageDescription = "La aplicación descubrirá y se conectará a dispositivos en su red";
NSLocationWhenInUseUsageDescription = "Se requiere su consentimiento antes de poder usar los servicios de ubicación y recomendar amigos cercanos";
NSMicrophoneUsageDescription = "\"Molistar\" necesita su consentimiento antes de que pueda realizar chat de voz";
NSPhotoLibraryAddUsageDescription = "\"Molistar\" necesita su consentimiento antes de que pueda almacenar fotos en el álbum";
NSPhotoLibraryUsageDescription = "\"Molistar\" necesita su consentimiento antes de que pueda acceder al álbum y seleccionar las imágenes que necesita cargar, y luego mostrarlas en su página de inicio personal para que otros lo vean";
NSUserTrackingUsageDescription = "Permítanos obtener su permiso de IDFA para brindarle actividades y servicios personalizados.Su información no se utilizará para otros fines sin su permiso.";

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
NSCameraUsageDescription ="\"MoliStar\" needs your consent before you can visit, take photos and upload your pictures, and then display them on your personal homepage for others to view";
NSLocalNetworkUsageDescription ="The app will discover and connect to devices on your network";
NSLocationWhenInUseUsageDescription = "Your consent is required before you can use location services and recommend nearby friends";
NSMicrophoneUsageDescription = "\"MoliStar\" needs your consent before it can conduct voice chat";
NSPhotoLibraryAddUsageDescription = "\"MoliStar\" needs your consent before it can store photos in the album";
NSPhotoLibraryUsageDescription = "\"MoliStar\" needs your consent before you can access the album and select the pictures you need to upload, and then display them on your personal homepage for others to view";
NSUserTrackingUsageDescription = "Please allow us to obtain your idfa permission to provide you with personalized activities and services. your information will not be used for other purposes without your permission";

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
NSCameraUsageDescription ="\"MoliStar\" needs your consent before you can visit, take photos and upload your pictures, and then display them on your personal homepage for others to view";
NSLocalNetworkUsageDescription ="The app will discover and connect to devices on your network";
NSLocationWhenInUseUsageDescription = "Your consent is required before you can use location services and recommend nearby friends";
NSMicrophoneUsageDescription = "\"MoliStar\" needs your consent before it can conduct voice chat";
NSPhotoLibraryAddUsageDescription = "\"MoliStar\" needs your consent before it can store photos in the album";
NSPhotoLibraryUsageDescription = "\"MoliStar\" needs your consent before you can access the album and select the pictures you need to upload, and then display them on your personal homepage for others to view";
NSUserTrackingUsageDescription = "Please allow us to obtain your idfa permission to provide you with personalized activities and services. your information will not be used for other purposes without your permission";

File diff suppressed because it is too large Load Diff