You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Unity iOS PostScript实现iOS原生弹窗本地化?

Unity iOS PostProcess自动化配置原生弹窗本地化

核心思路

Unity的PostProcessBuildAttribute脚本可以直接修改Xcode项目的project.pbxproj配置文件,自动将本地化的plist.strings文件关联到项目目标,并更新iOS所需的本地化设置,替代手动拖拽操作。

步骤1:准备本地化文件结构

在Unity项目中创建固定目录存放本地化文件,比如Assets/StreamingAssets/iOS/Localization,每个语言对应一个[lang].lproj文件夹,里面放置InfoPlist.strings(用于系统弹窗本地化,比如相机、相册权限提示):

Assets/StreamingAssets/iOS/Localization/
├─ zh-Hans.lproj/
│  └─ InfoPlist.strings
├─ en.lproj/
│  └─ InfoPlist.strings
└─ ja.lproj/
   └─ InfoPlist.strings

InfoPlist.strings的格式示例:

"NSCameraUsageDescription" = "需要访问相机以拍摄照片";
"NSPhotoLibraryUsageDescription" = "需要访问相册以选择照片";

步骤2:编写PostProcessBuild脚本

创建Editor脚本,实现自动化处理逻辑:

using UnityEditor;
using UnityEditor.Callbacks;
using UnityEngine;
using System.IO;
using UnityEditor.iOS.Xcode;

public class iOSLocalizationPostProcessor
{
    [PostProcessBuild(999)]
    public static void ConfigureLocalization(BuildTarget target, string pathToBuiltProject)
    {
        if (target != BuildTarget.iOS) return;

        // 路径配置
        string projectPath = Path.Combine(pathToBuiltProject, "Unity-iPhone.xcodeproj/project.pbxproj");
        string unityLocalizationDir = Path.Combine(Application.streamingAssetsPath, "iOS/Localization");
        string xcodeLocalizationDir = Path.Combine(pathToBuiltProject, "Localization");

        // 复制本地化文件到Xcode项目
        if (Directory.Exists(unityLocalizationDir))
        {
            // 先清空旧目录
            if (Directory.Exists(xcodeLocalizationDir))
                Directory.Delete(xcodeLocalizationDir, true);
            
            // 复制所有lproj文件夹
            foreach (var langDir in Directory.GetDirectories(unityLocalizationDir))
            {
                string langFolderName = Path.GetFileName(langDir);
                string destLangDir = Path.Combine(xcodeLocalizationDir, langFolderName);
                Directory.CreateDirectory(destLangDir);
                
                foreach (var file in Directory.GetFiles(langDir))
                {
                    File.Copy(file, Path.Combine(destLangDir, Path.GetFileName(file)), true);
                }
            }
        }

        // 加载并修改Xcode项目配置
        PBXProject pbxProject = new PBXProject();
        pbxProject.ReadFromFile(projectPath);

        string mainTargetGuid = pbxProject.GetUnityMainTargetGuid();
        string testTargetGuid = pbxProject.GetUnityTestTargetGuid();

        // 遍历所有本地化文件,添加到项目并设置本地化属性
        foreach (var langDir in Directory.GetDirectories(xcodeLocalizationDir))
        {
            string langCode = Path.GetFileName(langDir).Replace(".lproj", "");
            
            foreach (var plistFile in Directory.GetFiles(langDir))
            {
                string relativeFilePath = Path.Combine("Localization", Path.GetFileName(langDir), Path.GetFileName(plistFile));
                // 添加文件到Xcode项目
                string fileGuid = pbxProject.AddFile(relativeFilePath, relativeFilePath, PBXSourceTree.Source);
                
                // 将文件关联到主目标和测试目标
                pbxProject.AddFileToBuild(mainTargetGuid, fileGuid);
                pbxProject.AddFileToBuild(testTargetGuid, fileGuid);
                
                // 设置文件的本地化语言
                pbxProject.SetLocalization(fileGuid, langCode);
            }
        }

        // 配置项目本地化相关属性
        pbxProject.SetProjectProperty("LOCALIZATION_PREFERS_STRING_CATALOGS", "NO"); // 兼容传统strings文件,Xcode15+若用String Catalogs设为YES
        pbxProject.SetProjectProperty("CLANG_ENABLE_MODULES", "YES");

        // 保存项目配置
        pbxProject.WriteToFile(projectPath);

        // 更新Info.plist,添加支持的语言列表
        string infoPlistPath = Path.Combine(pathToBuiltProject, "Info.plist");
        PlistDocument plistDoc = new PlistDocument();
        plistDoc.ReadFromFile(infoPlistPath);

        // 创建或更新CFBundleLocalizations数组
        PlistElementArray langArray = plistDoc.root["CFBundleLocalizations"] as PlistElementArray;
        if (langArray == null)
            langArray = plistDoc.root.CreateArray("CFBundleLocalizations");
        
        // 避免重复添加语言
        langArray.values.Clear();
        foreach (var langDir in Directory.GetDirectories(xcodeLocalizationDir))
        {
            string langCode = Path.GetFileName(langDir).Replace(".lproj", "");
            langArray.AddString(langCode);
        }

        plistDoc.WriteToFile(infoPlistPath);
    }
}

关键说明

  1. 文件复制逻辑:将Unity中存放的本地化文件同步到Xcode项目的Localization目录,确保Xcode能找到这些文件。
  2. PBXProject操作:通过AddFile将文件纳入Xcode项目,SetLocalization绑定对应的语言区域,AddFileToBuild关联到编译目标。
  3. Info.plist更新:添加CFBundleLocalizations数组,明确告知iOS应用支持的语言列表,确保系统弹窗能正确加载对应语言的文案。
  4. 兼容性设置:LOCALIZATION_PREFERS_STRING_CATALOGS设为NO是为了兼容传统的.strings文件,若使用Xcode 15+的String Catalogs,可改为YES并调整文件类型。

测试验证

  1. 构建iOS项目后,打开Xcode,查看项目的Localization目录是否已包含所有lproj文件夹。
  2. 进入项目的Info标签页,查看Localizations列表是否自动添加了对应语言。
  3. 运行应用,切换系统语言,验证原生弹窗的文案是否正确显示对应语言。

内容的提问来源于stack exchange,提问作者Xin Meng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 23:30:54