前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >iOS小技能:APP内的本地化语言切换(案例:登录界面切换中英文)

iOS小技能:APP内的本地化语言切换(案例:登录界面切换中英文)

作者头像
公众号iOS逆向
发布于 2022-08-22 03:39:39
发布于 2022-08-22 03:39:39
3.3K00
代码可运行
举报
文章被收录于专栏:iOS逆向与安全iOS逆向与安全
运行总次数:0
代码可运行

前言

原理:

  1. 从指定的表和包中返回字符串的本地化版本: NSLocalizedStringFromTableInBundle(key, table, _bundle, nil)
  2. 切换语言生效方式:采用销毁根控制器,重新进入一次
  3. 本地化字符串指定参数顺序

从CSDN下载【iOS APP 内的国际化切换】demo源码:https://download.csdn.net/download/u011018979/19089505

I 字符串的本地化

1.1 用法

  • 创建字符串资源文件Localizable.strings

在这里插入图片描述

  • 为Localizable.strings添加多语言支持

选 make Localize代表会将Localizable.strings加入到英语的本地化文件夹en.lproj中去

在这里插入图片描述

Localizable.strings(English)对应en.lproj文件夹中的Localizable.strings文件 Localizable.strings(Chinese)对应zh-Hans.lproj文件夹中的Localizable.strings文件

  • 在资源文件Localizable.strings配置字符串对应的key和value。

en.lproj/Localizable.strings

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static NSString * const kSystem      = @"SystemDefault";

static NSString * const kCH          = @"zh-Hans";
static NSString * const kEN          = @"en";


static NSString * const kProj        = @"lproj";
static NSString * const kLanguageSet = @"kLanguageSet";
"Connected" = "Connected";
"Tip"="Tip";

zh-Hans.lproj/Localizable.strings

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
"Connected" = "已连接";
"Tip"="提示";

在这里插入图片描述

  • 在代码中使用NSLocalizedString(key, comment)来读取本地化字符串,key是Localizable.strings文件中等号左边的字符串,comment纯粹是注释
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 #define NSLocalizedString(key, comment) \
     [NSBundle.mainBundle localizedStringForKey:(key) value:@"" table:nil]
#define NSLocalizedStringFromTable(key, tbl, comment) \
     [NSBundle.mainBundle localizedStringForKey:(key) value:@"" table:(tbl)]
#define NSLocalizedStringFromTableInBundle(key, tbl, bundle, comment) \
     [bundle localizedStringForKey:(key) value:@"" table:(tbl)]
#define NSLocalizedStringWithDefaultValue(key, tbl, bundle, val, comment) \
     [bundle localizedStringForKey:(key) value:(val) table:(tbl)]

1.2 语言的切换

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//程序的本地化,引用国际化的文件
#define QCTLocal(x, ...) HZLocalizedString(x, nil)

#define HZLocalizedString(key, comment)               HZLocalizedStringFromTable(key, @"Localizable", nil)
#define HZLocalizedStringFromTable(key, tbl, comment) [[HZLanguageManager defaultManager] stringWithKey:key table:tbl]




/**

 @param key <#key description#>
 @param table Localizable
 @return <#return value description#>
 */
- (NSString *)stringWithKey:(NSString *)key table:(NSString *)table
{
    //假如为跟随系统
    if (self.languageType==HZLanguageTypeSystem) {
        return  NSLocalizedString(key, nil);
    }
    
    //返回对应国际化文字
    if (_bundle) {
        return  NSLocalizedStringFromTableInBundle(key, table, _bundle, nil);
    }
    
    return NSLocalizedStringFromTable(key, table, nil);
}





// 使用QCTLocal读取本地化字符串

        [LBAlertController showAlertTitle:QCTLocal(@"tips") content:QCTLocal(@"str_cann_printer") cancelString:QCTLocal(@"cancel") cancleBlock:nil sureString:QCTLocal(@"sure") sureBlock:^{

如果没有对字符串进行本地化 或者 找不到key对应的值,NSLocalizedString将直接返回key这个字符串

重置TableBundle

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- (void)resetBundle{
    
    NSLog(@"resetBundle:%@",_languageString);
    
    if ([_languageString isEqualToString:kEN] || [_languageString isEqualToString:kCH]) {
        NSString *path = [[NSBundle mainBundle] pathForResource:_languageString ofType:kProj];
        self.bundle = [NSBundle bundleWithPath:path];
    }
}

1.3 强制为中文

由于审核时境外IP无法访问,决定去掉英文版本。

https://blog.csdn.net/z929118967/article/details/89277538

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    // 由于审核时,境外IP无法访问,决定去掉英文版本

- (void)setLanguageType:(HZLanguageType)languageType{
    //HZLanguageTypeChineseSimple
    languageType =HZLanguageTypeChineseSimple;
     _languageString = kCH;//强制为中文

    _languageType =languageType;
    
}
// 中英文切换
- (void)changeLanguageType:(HZLanguageType)type;
{
    if (self.currentLanguageType == type) {
        return;
    }
    
    self.languageType = type;
    
    switch (self.languageType) {
            
        case HZLanguageTypeSystem:
            
            self.languageString=kSystem;
            break;
        case HZLanguageTypeEnglish:
            
            self.languageString = kEN;
            break;
        case HZLanguageTypeChineseSimple:
            
            self.languageString = kCH;
            break;

    }
    
    //bundle 设置
    [self resetBundle];
    
    //设置语言,并作记录保存
    [[NSUserDefaults standardUserDefaults] setObject:_languageString forKey:kLanguageSet];
    [[NSUserDefaults standardUserDefaults] synchronize];
    
    //使用通知更改文字    [[NSNotificationCenter defaultCenter] postNotificationName:kNoticeLanguageChange object:nil];
}


1.4 本地化字符串指定参数顺序

对于在中英文语法的区别,在本地化字符串的时候,我们常常需要调整stringWithFormat的参数顺序

  • iOS本地化字符串指定参数顺序:应用场景:app内的多语言切换

文章:https://kunnan.blog.csdn.net/article/details/108793150 原理:在%和@中间加上数值

(1

,2$),数字代表参数的顺序

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
"FORMAT" = "I am %2$@ from '%1$@'";

II 自定义解析本地化字符串的工具类LanguageManager

2.1 代码实现

  • LanguageManager

从CSDN下载【iOS APP 内的国际化切换】demo源码:https://download.csdn.net/download/u011018979/19089505

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#import <Foundation/Foundation.h>

#define HZLocalizedString(key, comment)               HZLocalizedStringFromTable(key, @"Localizable", nil)
#define HZLocalizedStringFromTable(key, tbl, comment) [[HZLanguageManager defaultManager] stringWithKey:key table:tbl]

static NSString * const kNoticeLanguageChange = @"kNoticeLanguageChange";


typedef NS_ENUM(NSUInteger, HZLanguageType) {
    HZLanguageTypeSystem,
    HZLanguageTypeEnglish,
    HZLanguageTypeChineseSimple,
};

@interface HZLanguageManager : NSObject

@property (nonatomic, assign, getter=currentLanguageType) HZLanguageType languageType;

+ (instancetype)defaultManager;

- (void)changeLanguageType:(HZLanguageType)type;
- (NSString *)stringWithKey:(NSString *)key table:(NSString *)table;
- (HZLanguageType)currentLanguage;

+ (BOOL )isEN;


  • LanguageManager.h .m
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static NSString * const kSystem      = @"SystemDefault";

static NSString * const kCH          = @"zh-Hans";
static NSString * const kEN          = @"en";


static NSString * const kProj        = @"lproj";
static NSString * const kLanguageSet = @"kLanguageSet";

@interface HZLanguageManager()

@property (nonatomic, strong) NSBundle *bundle;
@property (nonatomic, strong) NSString *languageString;

@end

@implementation HZLanguageManager

+ (instancetype)defaultManager
{
    static dispatch_once_t onceToken;
    static HZLanguageManager *manager;
    dispatch_once(&onceToken, ^{
        if (!manager) {
            manager = [[HZLanguageManager alloc] init];
        }
    });
    return manager;
}

- (instancetype)init
{
    self = [super init];
    if (!self) {
        return nil;
    }
    //取字段看是哪种语言
    NSString *tempStr = [[NSUserDefaults standardUserDefaults] objectForKey:kLanguageSet];
    //    NSString *path;
    
    //假如用户没有设置过语言
    if (!tempStr) {
        tempStr=kSystem;
    }
    
    self.languageString = tempStr;
    
    
    if ([self.languageString isEqualToString:kCH]) {//为中文
        
        self.languageType = HZLanguageTypeChineseSimple;
        
    }else if ([self.languageString isEqualToString:kEN]) {//为英文
        
        self.languageType = HZLanguageTypeEnglish;
        
    }else if([self.languageString isEqualToString:kSystem]){//为系统默认
        
        self.languageType= HZLanguageTypeSystem;
        
        if([self isENLanguage]){//HZLanguageManager
            self.languageType = HZLanguageTypeEnglish;

        }else{
            self.languageType = HZLanguageTypeChineseSimple;

        }
        
        
    }
    
    if ([_languageString isEqualToString:kEN] || [_languageString isEqualToString:kCH]) {
        NSString *path = [[NSBundle mainBundle] pathForResource:_languageString ofType:kProj];
        self.bundle = [NSBundle bundleWithPath:path];
    }
    
    NSLog(@"当前的语言    HZLanguageTypeSystem HZLanguageTypeEnglish HZLanguageTypeChineseSimple:%lu",(unsigned long)self.languageType);
    
    return self;
}



- (void)changeLanguageType:(HZLanguageType)type;
{
    if (self.currentLanguageType == type) {
        return;
    }
    
    _languageType = type;
    switch (type) {
        case HZLanguageTypeSystem:
            
            self.languageString=kSystem;
            break;
        case HZLanguageTypeEnglish:
            
            self.languageString = kEN;
            break;
        case HZLanguageTypeChineseSimple:
            
            self.languageString = kCH;
            break;

    }
    
    //bundle 设置
    [self resetBundle];
    
    //设置语言,并作记录保存
    [[NSUserDefaults standardUserDefaults] setObject:_languageString forKey:kLanguageSet];
    [[NSUserDefaults standardUserDefaults] synchronize];
    
    //使用通知更改文字    [[NSNotificationCenter defaultCenter] postNotificationName:kNoticeLanguageChange object:nil];
}

- (void)resetBundle{
    if ([_languageString isEqualToString:kEN] || [_languageString isEqualToString:kCH]) {
        NSString *path = [[NSBundle mainBundle] pathForResource:_languageString ofType:kProj];
        self.bundle = [NSBundle bundleWithPath:path];
    }
}

- (NSString *)stringWithKey:(NSString *)key table:(NSString *)table
{
    //假如为跟随系统
    if (self.languageType==HZLanguageTypeSystem) {
        return  NSLocalizedString(key, nil);
    }
    
    //返回对应国际化文字
    if (_bundle) {
        return  NSLocalizedStringFromTableInBundle(key, table, _bundle, nil);
    }
    
    return NSLocalizedStringFromTable(key, table, nil);
}

-(HZLanguageType)currentLanguage{
    //获取当前语言
    //  NSString *tempStr = [[NSUserDefaults standardUserDefaults] objectForKey:kLanguageSet];
    //    if ([tempStr rangeOfString:@"zh"].length) {
    ////        tempStr = kCH;
    //        return HZLanguageTypeChineseSimple;
    //    }else if([tempStr isEqualToString:kEN]){
    ////        tempStr = kEN;
    //        return HZLanguageTypeEnglish;
    //    }else {//if([tempStr isEqualToString:kSystem])
    //    
    //        return HZLanguageTypeSystem;
    //    }
    return    self.languageType;
}


+ (NSArray *)english {
    return @[@"en", @"en-CN"];
}

+ (NSArray *)chineseHans {
    return @[@"zh-Hans", @"zh-Hans-CN"];
}

+ (NSArray *)chineseHant {
    return @[@"zh-Hant", @"zh-Hant-CN"];
}




/**
 (lldb) po [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"]
 <__NSCFArray 0x2833357a0>(
 zh-Hans-AM,
 en-AM,
 en-GB,
 ru-AM,
 zh-Hant-AM,
 zh-Hant-HK
 )
 
第一个就是用户设置的语言

 @return
 */
- (BOOL )isENLanguage {
//    NSString *language = [[NSUserDefaults standardUserDefaults] objectForKey:GHLLanguageKey];
    
//    if (){
//    if ([HZLanguageManager defaultManager].currentLanguage==HZLanguageTypeEnglish) {

    if (self.currentLanguage == HZLanguageTypeEnglish) {

    return YES;
    }
    
    
    
//    if () {
        NSArray *languages = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"];
        NSString *language =  languages.firstObject;
        
//    }
    
//    if([[HZLanguageManager chineseHans] containsObject:language] || [[HZLanguageManager chineseHant] containsObject:language] ){
        if([language containsString:@"zh-Hans"] || [language containsString:@"zh-Hant"] ){

        
        return NO;
        }else{
            return YES;

        }
    
}



+ (BOOL )isEN{
    
    if([HZLanguageManager defaultManager].currentLanguage == HZLanguageTypeEnglish ){
        //                make.width.mas_equalTo(kAdjustRatio(73 * 3));
        return YES;
        
    }else{
        //                make.width.mas_equalTo(kAdjustRatio(50 * 3));
//        make.left.equalTo(weakSelf.contentView).offset(kAdjustRatio(20));
//        make.right.equalTo(weakSelf.contentView).offset(- kAdjustRatio(20));
//
        return NO;

    }

}
@end

2.2 strings文件的文本内容过长导致key 失效的解决方案

/consts/Localizable/en.lproj/Localizable.strings 文本内容太长了。 会导致key 失效。

  • 解决方案

新增一个table来存储,解析的时候从两个文件查找。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 new file:   retail/retail/class/consts/Localizable/en.lproj/Localizable1.strings
 new file:   retail/retail/class/consts/Localizable/zh-Hans.lproj/Localizable1.strings

  • 读取本地字符串的代码:如果你的字符串资源文件名不是Localizable.strings,如KN.strings,那么你就得使用NSLocalizedStringFromTable()、NSLocalizedStringFromTableInBundle来读取本地化字符串:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- (NSString *)stringWithKey:(NSString *)key table:(NSString *)table
{
    //假如为跟随系统
    if (self.languageType==HZLanguageTypeSystem) {
        return  NSLocalizedString(key, nil);
    }
    
    //返回对应国际化文字
    if (_bundle) {// 修改成为,从另外一个文件找,先从文件找,如果找不到就从文件二找。
        //NSLocalizedStringFromTableInBundleWithKey
        return [self NSLocalizedStringFromTableInBundleWithKey:key table:table];
        return  NSLocalizedStringFromTableInBundle(key, table, _bundle, nil);
        
        
        
    }
    
    return NSLocalizedStringFromTable(key, table, nil);
}



/**

如果你的字符串资源文件名不是Localizable.strings,如KN.strings,那么你就得使用NSLocalizedStringFromTable()来读取本地化字符串:


*/
//{// 修改成为,从另外一个文件找,先从文件找,如果找不到就从文件二找。
- (NSString*)NSLocalizedStringFromTableInBundleWithKey:(NSString *)key table:(NSString *)table{
    NSString* tmp = key;
    if(_bundle){
        
        tmp =NSLocalizedStringFromTableInBundle(key, table, _bundle, nil);

        if([tmp isEqualToString:key]){
            // 继续从备份表查找
            
            NSLog(@"开始从Localizable1 找key:%@", tmp);
            tmp =NSLocalizedStringFromTableInBundle(key, @"Localizable1", _bundle, nil);
//            NSLog([NSString stringWithFormat:@"结束从Localizable1 找key:%@",tmp]);
            NSLog(@"结束从Localizable1 找key:%@", tmp);


        }
    }
    return tmp;

    
    
    
}



III info.plist 的国际化

  • 新建一个 .strings文件,叫做InfoPlist.strings(文件名必须是这个)
  • 新建以后,点击右侧的 localized 才有意义。
  • 关键的步骤来了,这时候,点击我们的info.plist,右键选择open as source code 查看我们所要获取权限的原始 key

在这里插入图片描述

Info.plist中的CFBundleDisplayName的key决定了应用程序的名称

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
"NSMicrophoneUsageDescription" = "Allow this app to use your microphone for decibel detection and sound recording; audio is recorded locally only and is not sent to anyone, only for decibel detection and sound variation.";

IV 案例

4.1 《用户协议及隐私政策》弹框(包含超链接属性)【本文包含完整demo源码,demo支持中英文切换】

iOS《用户协议及隐私政策》弹框(包含超链接属性)【本文包含完整demo源码,demo支持中英文切换】 | 蓄力计划

https://kunnan.blog.csdn.net/article/details/103902362

4.2 登录界面切换中英文

  • AppDelegate: 设置默认的语言
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    if([LanguageManager isEN] ){
//        _titleLab.font = kPingFangFont(10);
        [[LanguageManager defaultManager] changeLanguageType: HZLanguageTypeEnglish];

        NSLog(@"当前位英文版本");
        
    }else{
//        _titleLab.font = kPingFangFont(12);
        NSLog(@"当前位中文版本");
        [[HZLanguageManager defaultManager] changeLanguageType: HZLanguageTypeChineseSimple];

        
    }

}

https://github.com/zhangkn/LanguageManager/tree/main/iUIPageControlFix4iOS14/LanguageManager

  • 搭建切换按钮:languageLab

处理切换中英文语言的动作事件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

- (UILabel *)languageLab{
    if (!_languageLab) {
        _languageLab = [[UILabel alloc]init];
        _languageLab.textColor = rgb(51,51,51);
        _languageLab.font = kBoldFont(15);
        
        
        _languageLab.textAlignment = NSTextAlignmentRight;
        
        
        
        // 根据配置进行显示
//        typedef NS_ENUM(NSUInteger, HZLanguageType) {
//            HZLanguageTypeSystem,
//            HZLanguageTypeEnglish,
//            HZLanguageTypeChineseSimple,
//        };

        // 获取配置信息
        
        //设置选中的语言
        if ([HZLanguageManager defaultManager].currentLanguage==HZLanguageTypeSystem) {
//            self.seletedIndex=@0;
            
            
            
            
        }
       else if ([HZLanguageManager defaultManager].currentLanguage==HZLanguageTypeChineseSimple) {
//            self.seletedIndex=@1;
//           _languageLab.text = @"";
           _languageLab.text = @"English";


        }
       else  if ([HZLanguageManager defaultManager].currentLanguage==HZLanguageTypeEnglish) {
//            self.seletedIndex=@2;
           
           _languageLab.text = @"简体中文";

       }else{
           
//           _languageLab.text = @"简体中文";

           
       }
        

        
        
        //
//        ti ti阿佳
        //
        
        _languageLab.userInteractionEnabled = YES;
        
        
        
        
        [self addSubview:_languageLab];
        __weak __typeof__(self) weakSelf = self;

        [_languageLab mas_makeConstraints:^(MASConstraintMaker *make) {
           
            make.top.equalTo(weakSelf).offset(36);
            make.right.equalTo(weakSelf).offset(-kAdjustRatio(16));
            
            make.size.mas_equalTo(CGSizeMake(kAdjustRatio(100), kAdjustRatio(40)));

            
            
        }];
        
        
        UITapGestureRecognizer *cutTap = [[UITapGestureRecognizer alloc] init];
//        __weak __typeof__(self) weakSelf = self;
        
        [[cutTap rac_gestureSignal] subscribeNext:^(id x) {
            
            

            switch ([HZLanguageManager defaultManager].currentLanguage) {
                case HZLanguageTypeSystem:
                    {
                        
                    }
                    break;
                    
                case HZLanguageTypeEnglish:
                {
                    
                    [[HZLanguageManager defaultManager] changeLanguageType: HZLanguageTypeChineseSimple];

                    weakSelf.languageLab.text = @"简体中文";

                }
                    break;
                    
                case HZLanguageTypeChineseSimple:
                {
                    [[HZLanguageManager defaultManager] changeLanguageType: HZLanguageTypeEnglish];

                    weakSelf.languageLab.text = @"English";

                }
                    break;
                    

                    
                default:
                {
                    
                }
                    break;
            }
            
            [ AccountLoginView rootViewController4nil];
            
            
        }];
        [_languageLab addGestureRecognizer:cutTap];

        
    }
    return _languageLab;
}


+ (void) rootViewController4nil{
    
    //销毁 root
    UIWindow *oldWindow=[UIApplication sharedApplication].keyWindow;
    oldWindow.rootViewController=nil;
    
    //新 root
    UIWindow *newWindow = [UIApplication sharedApplication].keyWindow;
    
    
    AccountLoginViewController *VC = [[AccountLoginViewController alloc]init];
    
    HWNavigationController *NA = [[HWNavigationController alloc]initWithRootViewController:VC];
    
    
    
    [AccountLoginView restoreRootViewController:NA newWindow:newWindow];

}

/**
 UIModalTransitionStyleCoverVertical = 0, //从下到上盖上进入
 
 UIModalTransitionStyleFlipHorizontal, //水平翻转
 
 UIModalTransitionStyleCrossDissolve, //渐变出现
 
 #if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_3_2
 
 UIModalTransitionStylePartialCurl, //类似翻页的卷曲
 


 @param rootViewController <#rootViewController description#>
 @param newWindow <#newWindow description#>
 https://github.com/codeRiding/CRProject/blob/165886b8426fa43b52e76e659b8e18496e2fa8c8/CRProject/Classes/Expand/Tool/CRChangeVC.m
 */
+ (void)restoreRootViewController:(UIViewController *)rootViewController newWindow:(UIWindow*)newWindow
{
    typedef void (^Animation)(void);
    UIWindow* window =  newWindow;
//
    rootViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
//UIModalPresentationPopover
    //UIModalPresentationNone
//    rootViewController.modalPresentationStyle = UIModalPresentationOverFullScreen;//UIModalPresentationOverFullScreen

//    UIModalTransitionStyleCoverVertical = 0,
//    UIModalTransitionStyleFlipHorizontal __TVOS_PROHIBITED,
//    UIModalTransitionStyleCrossDissolve,
//    UIModalTransitionStylePartialCurl
//    rootViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
    Animation animation = ^{
        BOOL oldState = [UIView areAnimationsEnabled];
        [UIView setAnimationsEnabled:NO];
//        [UIApplication sharedApplication].keyWindow.rootViewController = rootViewController;
                        [newWindow switchWithRootViewController:rootViewController];

        [UIView setAnimationsEnabled:oldState];
    };
    //
    [UIView transitionWithView:window
                      duration:0.5f
                       options:UIViewAnimationOptionTransitionCrossDissolve
                    animations:animation
                    completion:nil];

}

4.3 本地化字符串指定参数顺序

对于在中英文语法的区别,在本地化字符串的时候,我们常常需要调整stringWithFormat的参数顺序

原理:在%和@中间加上数值(1,2$),数字代表参数的顺序 文章:https://blog.csdn.net/z929118967/article/details/108793150

see also

  • iOS精品资源汇总:(持续更新)

https://kunnan.blog.csdn.net/article/details/112865806

  • 合并develop到master,并打版本tag

https://blog.csdn.net/z929118967/article/details/104572619

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-07-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 iOS逆向 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
从SAP最佳业务实践看企业管理(147)-供应商管理库存
什么是供应商管理库存 供应商管理库存(Vendor managed inventory,简称VMI),指供应商等上游企业基于其下游客户的生产经营、库存信息,对下游客户的库存进行管理与控制。具体来说VMI是一种以用户和供应商双方都获得最低成本为目的,在一个共同的协议下由供应商管理库存,并不断监督协议执行情况和修正协议内容,使库存管理得到持续地改进的合作性策略。 这种库存管理策略打破了传统的各自为政的库存管理模式。体现了供应链的集成化管理思想,适应市场变化的要求,是一种新的、有代表性的库存管理思想。 供应商管理
SAP最佳业务实践
2018/03/27
1.5K0
从SAP最佳业务实践看企业管理(147)-供应商管理库存
揭开数据分析中的规范性分析:从入门到精通
在当今数据驱动的世界,数据分析已经成为每个行业的核心技能。无论你是初入职场的新人,还是经验丰富的资深分析师,掌握数据分析的技巧都是不可或缺的。然而,数据分析不仅仅是简单的数字运算或趋势发现。更为复杂的分析方法,如规范性分析,可以帮助你在面对多种选择时,做出最优决策。
theskylife
2024/08/15
3101
从SAP最佳业务实践看企业管理(139)-库存订货策略
一、期间订货法(POQ,Period Order Quantity) 计划订单产生来满足某期间的需求,用户只需输入订货间隔期,系统会依订货间隔期栏位设定的天数,先计算该期间各天的净需求,然后按期间将各天的净需求进行汇总后进行批量调整,在各期间的第一天生成计划订单。 批量调整的公式为:计划订单量=最小订货量+取大整数【(净需求-最小订货量)/批量增量】*批量增量。 温馨提醒:对于周期性订货的物料(如供应商有良好的信义,且需求相对稳定,采用周期订货对双方都便利的话,可以采用该类设置),同时要设定订货间隔期。 二
SAP最佳业务实践
2018/03/27
2K0
从SAP最佳业务实践看企业管理(139)-库存订货策略
库存管理中常用的计算公式及评估方法!(干货)
从公式中可以看出存货周转率是用来衡量一个期间内存货能周转几次,数值越大,库存的利用率越高。
物流IT圈
2019/10/16
5.6K0
从SAP最佳业务实践看企业管理(152)-生产物流-生产线物流规划
企业的运营过程中,物流、资金流和信息流贯穿始终,三位一体,不可分割。物流是最基本的活动,相对于信息流和资金流,物流规划的科学性对企业的整体效益有着决定性的影响。 本文的切入点是生产线的物流规划,利用现有条件,比如生产节拍、工艺流程、单元化包装、场地面积等参数,结合ABC分类和流量平衡图进行分析,规划物料的运输数量、运输时间、线边存放方式、线边库存量的范围、运输方式、运输路线等,即PFEP-Planning For Every Part包含的内容。之后,运用PFEP的结果,结合场地面积,制作生产线定置图。分析
SAP最佳业务实践
2018/03/27
1.2K0
从SAP最佳业务实践看企业管理(152)-生产物流-生产线物流规划
SAP 呆滞库存的计算
呆滞就是不流动,物料呆滞多久才是呆滞?可谓标准不同,说法各异,有的认为物料的最后异动日至盘查时,其时间间隔超过180天者,称为呆滞物料。有的说超过3个月不流动就算呆滞,也有的说超过1年不流动才算呆滞。总之,物料存量过多,耗用量极少,而库存周转率极低的物料就是呆滞物料。每个公司划分标准不同,例如笔者公司就规定:对质量(规格、材质)不符合标准的原材料、外购件及外协件,存储超过1个月,已无使用机会,或虽有使用机会但用料极少的;对良好状态的原材料、外购件及外协件,存储超过3个月,在以后的生产中没有机会使用或者很少使用的;对成品、半成品,凡因质量不符合标准、在制或制成后客户取消订单、过多库存等因素影响,储存超过1年以上的,都算作呆滞物料。
用户5495712
2019/08/27
1.5K0
SAP 呆滞库存的计算
智慧供应链的学习笔记(库存管理、配补货、仓间调拨、控制塔等)
笔者在公司中参与了智慧供应链的项目,由于确实与笔者之前所研究的差异较大,从而陆陆续续也对该方向做过一些学习与调研,以此做记。
悟乙己
2022/05/11
8.2K1
智慧供应链的学习笔记(库存管理、配补货、仓间调拨、控制塔等)
数据分析八大模型:人货场模型
之前分享了销售分析的基本做法,今天来分享一个销售分析最常用的模型:人货场模型。这是来源于传统零售业的经典分析模型,在电商环境里其实也能用。大家一起来看一下。
码工小熊
2021/12/22
1.6K0
热文回顾|供应商管理库存VMI在轨道交通行业中的应用
摘 要:随着国有企业现代企业制度的建立,库存管理工作被赋予更高要求及新的内涵。库存管理是企业生产经营过程中不可缺少的重要组成部分,同时也是供应链管理的重要组成部分,更是供应链上作为各节点的企业实现合作及供应链实现集成管理的关键所在。轨道交通行业在库存管理中引入VMI理念对企业自身和供应商都有重大意义,有利于降低整体库存水平,减少物流成本,提高库存周转率。本文选取无锡地铁在库存管理应用VMI理念的实例加以阐述分析,为其他轨道交通企业提供经验借鉴。
用户9868602
2023/02/27
4670
热文回顾|供应商管理库存VMI在轨道交通行业中的应用
写给供应链产品经理:库存管理与系统设计
在过去,各地库房分散管理,互不透明,总部无法集中把控和调度,导致库存分布不平均,库存成本积压严重。
物流IT圈
2019/07/30
5.1K0
写给供应链产品经理:库存管理与系统设计
数据分析实例:用统计学解决杂货店产品库存问题
统计学,在很多人看来有点是高高在上不食人间烟火的存在,因为在实际生活中用到的情况很少。事实上,不实用的假象,主要在于统计学的使用是有一定门槛的。这里就以一个案例来说明,统计学在生活的使用实例。
沉默的白面书生
2019/03/08
1.5K0
数据分析实例:用统计学解决杂货店产品库存问题
零售业数据分析那些事儿
随着大数据时代的到来,数据分析已经成为了零售业非常重要的一环,也是精细化运营的基础。零售业数据分析包括:
静一
2018/03/16
9090
物流大数据简述
在大数据时代背景下,存在于社会任何行业、组织及个人不可能独善其身,或者成为数据贡献者,或者成为数据采集者。物流行业是近些年快速发展起来的朝阳行业,正是互联网技术的发展催生出的电子商务给物流行业带来了前所未有机遇。
物流IT圈
2019/09/03
2.9K0
吐血整理!万字原创读书笔记,数据分析的知识点全在这里了
导读:今天这篇文章是「大数据」内容合伙人JaneK关于《Python数据分析与数据化运营》的一篇读书笔记。在大数据公众号后台对话框回复合伙人,免费读书、与50万「大数据」同行分享你的洞见。
IT阅读排行榜
2019/11/15
1.5K0
食品库存模块场景介绍,SCM协同系统助力企业实现仓储管理信息化
随着互联网新消费时代的来临,消费需求呈现出越来越个性化、精细化的趋势,作为关系国计民生的食品行业正迎来全新转型。在数字化进程加快、新老品牌同台竞技、新消费理念流行的今天,危机和机遇并存下,食品企业究竟该如何布局供应链,实现逆势增长?
数商云
2023/01/03
3540
食品库存模块场景介绍,SCM协同系统助力企业实现仓储管理信息化
数商云:产业互联网时代下快消品行业供应链管理模式探索
互联网业界有句名言:“所有还没被互联网改变的行业,终究都将被互联网改变”。如今只要我们想象得到的行业,几乎都正面临传统行业和电商之间的博弈。快消品这一曾经风光无限的传统线下销售优势行业,也在这一股互联网电商革命浪潮中首当其冲的被狠狠的革了一命。
数商云市场营销总监
2022/03/31
4480
工业大数据在企业运营中可落地的八大应用
导读:每个企业都有自己的规划和自己企业在运营环节的管理最佳实践,大数据对促进供应链中的生产环节产生了前所未有的巨大影响,那么大数据在企业运营中到底有哪些应用值得我们关注?本文结合自己企业的发展和管理,
钱塘数据
2018/03/01
9580
工业大数据在企业运营中可落地的八大应用
从SAP最佳业务实践看企业管理(70)-SOP-制造与生产
制造与生产 制造与生产貌似是一样的,很多企业制造与生产隶属于同一个部门,但是制造与生产的关注点还是有区别的。 所谓制造,就是在确保品质的前提下,在生产现场对工作人员、机械设备、加工材料的使用实施合理化的管理,使其按照技术部门的工艺与技术规范要求,保证准时完成生产计划。需要注意的是,准时完成生产计划绝不是超额生产。生产计划取决于客户需求,物料的采购都是经过精确计算的,超产意味着产品积压和原料缺货。 所谓生产,是要保证顾客提出(预计)生产量,对产品品种、数量进行日程计划,对作业进度进行检查,对定购的原材料与零部
SAP最佳业务实践
2018/03/26
7370
库存管理常用考核指标
从公式中可以看出存货周转率是用来衡量一个期间内存货能周转几次,数值越大,库存的利用率越高。
用户5495712
2019/05/29
3K0
python数据分析——数据分析的数据模型
数据分析的数据模型是决策支持系统的重要组成部分,它通过对大量数据的收集、整理、分析和挖掘,为企业提供有价值的信息,以支持企业的战略规划和日常运营。数据模型的选择和应用,直接关系到数据分析的准确性和有效性,进而影响企业的决策质量和市场竞争力。
鲜于言悠
2024/03/20
3250
python数据分析——数据分析的数据模型
推荐阅读
相关推荐
从SAP最佳业务实践看企业管理(147)-供应商管理库存
更多 >
LV.1
这个人很懒,什么都没有留下~
目录
  • 前言
  • I 字符串的本地化
    • 1.1 用法
    • 1.2 语言的切换
    • 1.3 强制为中文
    • 1.4 本地化字符串指定参数顺序
  • II 自定义解析本地化字符串的工具类LanguageManager
    • 2.1 代码实现
    • 2.2 strings文件的文本内容过长导致key 失效的解决方案
  • III info.plist 的国际化
  • IV 案例
    • 4.1 《用户协议及隐私政策》弹框(包含超链接属性)【本文包含完整demo源码,demo支持中英文切换】
    • 4.2 登录界面切换中英文
    • 4.3 本地化字符串指定参数顺序
  • see also
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档