zoukankan      html  css  js  c++  java
  • IOS APP 国际化(实现不跟随系统语言,不用重启应用,代码切换stroyboard ,xib ,图片,其他资源)

    此问题已解决。请看:

     IOS APP 国际化 程序内切换语言实现 不重新启动系统(完美解决方案) 

     接了个变态的需求,要在程序内切换程序语言实现国际化。

    可以先看看这个,比较详细。

    http://blog.csdn.net/xwren362922604/article/details/17190061

    看完之后问题来了,

    1,工程里面大量的 xib  或 storyboard 里面的UI 设定了text ,怎么实现让它们动态加载语言【非设置系统语言重启】

    2,一个简单的思路,当代码触发切换语言 发个通知让 内存里的viewController 刷新UI的text 。[工程里这么都vc 每个都加 岂不累死]

    所有 接下来还可完善下。

    1,切换语言,重新加载window 的根视图。根据不同语言。【搜下网上的storyboard 国际化】

    你会发现 你操作后 xcode 为Main storyboard 添加了三个 文件

    这里依这为理。base和你添加的语言。
    你在这些文件上右键 show in finder 。

    看到那三个文件夹没 .lproj  这里是对应语言的 资源文件。你切换语言是 拿到当前语言eg: en 拼路径en.lproj

    [[NSBundle mainBundle] pathForResource:userLanguage ofType:@"lproj"];

    根据path 得到

    NSBundle

    熟悉吧。这玩意里面就是我们程序需要得资源文件。其实就是XX.lproj 文件夹里德东东

    初始化

    [UIStoryboard storyboardWithName:@"Main" bundle:bundle];

    我们更习惯于 后面的参数滋味nil 。 

    写到这有个问题。其实真正的main 放在了那个base 文件夹里。程序蹦了。让我们来干掉base 。千万别直接删除base文件。那样直接把main 。storyboard 删了。

    在这里

    点文件。右边栏。去掉base 沟。不要管警告。

    再看

    现在可以了。分别在两个文件夹了。

     

    遗留问题:如果支持很多语言,程序会变的很大.有解决的可以交流下

    这里可以附上关于 Base 文件的信息,

    http://samwize.com/2012/11/22/warning-do-not-use-base-internationalization-in-ios-5/

    如里面介绍,iOS 5不支持国际化 Base。 它是在ios6引入的。

     

    2, 写一个vc 基类。注册 和 移除  通知。对于自动刷新vc 内的 UI 。可以在基类里加个数组变量 【blok 的】

    在subVC,这里注意防止循环引用。_weak

    在superVC

    遍历执行。实现自动刷新

    如果你国际化后 还有接着修改storyboard 你在手动去添加 ui 到国际化文件 。string  发现不起作用了。苹果给提供了命令

    ibtool MainStoryboard.storyboard --generate-strings-file New.strings (你也可以取别的名字(New.strings))

     

    每次改完都要执行下确实挺麻烦。网上有个xcode脚本 可以在每次bulid 时帮我们完成,见下面博客:

    http://oleb.net/blog/2013/02/automating-strings-extraction-from-storyboards-for-localization/

    整理出得脚本,注释挺详细了。

    storyboardExt=".storyboard"

    stringsExt=".strings"

    newStringsExt=".strings.new"

    oldStringsExt=".strings.old"

    localeDirExt=".lproj"

     

    # Find storyboard file full path inside project folder

    for storyboardPath in `find ${SRCROOT} -name "*$storyboardExt" -print`

    do

    # Get Base strings file full path

    baseStringsPath=$(echo "$storyboardPath" | sed "s/$storyboardExt/$stringsExt/")

     

    # Create strings file only when storyboard file newer

    #if find $storyboardPath -prune -newer $baseStringsPath -print | grep -q .; then

    # Get storyboard file name and folder

    storyboardFile=$(basename "$storyboardPath")

    storyboardDir=$(dirname "$storyboardPath")

     

    # Get New Base strings file full path and strings file name

    newBaseStringsPath=$(echo "$storyboardPath" | sed "s/$storyboardExt/$newStringsExt/")

    stringsFile=$(basename "$baseStringsPath")

    ibtool --export-strings-file $newBaseStringsPath $storyboardPath

    iconv -f UTF-16 -t UTF-8 $newBaseStringsPath > $baseStringsPath

    rm $newBaseStringsPath

     

    # Get all locale strings folder

    for localeStringsDir in `find ${SRCROOT} -name "*$localeDirExt" -print`

    do

    # Skip Base strings folder

    if [ $localeStringsDir != $storyboardDir ]; then

    localeStringsPath=$localeStringsDir/$stringsFile

     

    # Just copy base strings file on first time

    if [ ! -e $localeStringsPath ]; then

    cp $baseStringsPath $localeStringsPath

    else

    oldLocaleStringsPath=$(echo "$localeStringsPath" | sed "s/$stringsExt/$oldStringsExt/")

    cp $localeStringsPath $oldLocaleStringsPath

     

    # Merge baseStringsPath to localeStringsPath

    awk 'NR == FNR && /^/*/ {x=$0; getline; a[x]=$0; next} /^/*/ {x=$0; print; getline; $0=a[x]?a[x]:$0; printf $0" "}' $oldLocaleStringsPath $baseStringsPath > $localeStringsPath

     

    rm $oldLocaleStringsPath

    fi

    fi

    done

    #else

    #echo "$storyboardPath file not modified."

    #fi

    done

    以上可以做到 在后续修改sb文件后,脚本会自动 将新加内容 添加到 .string文件

    格式如下:

    /* Class = "IBUILabel"; text = "Test2"; ObjectID = "NT7-J3-MH3"; */

    "NT7-J3-MH3.text" = "Test2";

    默认重新生成.string文件后 会覆盖原来的 内容。但这里脚本使用正则表达式 合并了。有兴趣可以搜下 shell 文件的合并。这玩意挺强大的。

     

    使用脚本的前提是 你工程里用了base.lproj 。但上面讨论的 代码切换 sb 文件不能用 base ,而且要支持ios5 使用base 会奔溃掉。

    那只能编辑sb 文件时用 base ,之后运行把base 去掉。在运行;也就去掉base 的勾选。

     

    后续解决能不能 shell 将sb 文件拷贝到APP 包中对应的 语言.lproj 。这样不用每次编辑-运行 都要手动去base沟选。

    尝试了下,可以实现 。但app 里文件li sb 文件后缀名为.storyboardc  ,文件明明在 代码加载却报错。

    有兴趣可以下载demo 里de Debug_st.sh 正是解决这个问题的。#debug if   ....  fi 里的东西是 为了调试故意让它报错的,不影响

    搞定后会再次更新。。。

     

    可以在这里下载我的demo工程: 

    刷新storyboard + 代码刷新 文案

     git clone   git@github.com:githhhh/Test_Local_Two.git   

     

     

     

  • 相关阅读:
    【Android Studio安装部署系列】三十六、从Android Studio3.1.4升级到Android studio3.2【以及创建android p模拟器(未成功)】
    Android Studio升级到3.1.4后打开旧项目警告:The `android.dexOptions.incremental` property is deprecated and it has no effect on the build process.
    Activity、Fragment、Dialog基类简单整理
    Android项目目录结构模板以及简单说明【简单版】
    【Android Studio安装部署系列】四十、Android Studio安装Statistic插件(统计项目总行数)
    java对象池化技术
    Java中的常量池(字符串常量池、class常量池和运行时常量池)
    Java进阶——Java中的字符串常量池
    字符串常量池深入解析
    资源对象的池化, java极简实现,close资源时,自动回收
  • 原文地址:https://www.cnblogs.com/DamonTang/p/3898046.html
Copyright © 2011-2022 走看看