跳到主要内容

expo处理android+ios多语言问题

问题

我的多语言名称配置方法大概是:

  1. 在项目根目录放置一系列多语言名称的json(个人放在/locales/meta目录); 每个语言文件格式大致如下: 文件名最好完全和语言Tag一致,如zh-Hans.json等。
// en.json
{
"app_name": "iChingLife",
"CFBundleDisplayName": "iChingLife",
"NSContactsUsageDescription": "English version"
}
  1. 在expo项目的app.json中配置上述文件路径;
"expo": {
...
"locales": {
"zh-Hans": "./locale/meta/zh-Hans.json",
"zh-Hant": "./locale/meta/zh-Hant.json",
"ja": "./locale/meta/ja.json",
"en": "./locale/meta/en.json",
"ko": "./locale/meta/ko.json",
"es": "./locale/meta/es.json"
},
...
}

这样的方法对ios已经完全ok了,但在android build时会出错误。 原因是"CFBundleDisplayName","NSContactsUsageDescription"这两个iOS专用的项也会写入android/app/src/main/res目录下各种语言的values目录下的strings.xml中,和主values目录下的strings.xml有冲突。 以前我的处理方法很简单,一个个改文件(删除不必要项)。 但是在新版expo(v54+)下,此法失效,原因和之前splits控制大小的问题一样的。

解决方法

配置app.config.js,代码如下:


import fs from 'fs';
import path from 'path';
import baseConfig from './app.json';

const LANGS = ['zh-Hans', 'zh-Hant', 'ja', 'en', 'ko', 'es'] as const;
type Lang = (typeof LANGS)[number];

function readMeta(lang: Lang) {
const filePath = path.resolve(__dirname, 'locale', 'meta', `$ {
lang
}.json`);

return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
}

// 读取所有 meta
const meta: Record < Lang,
any > =Object.fromEntries(LANGS.map((lang) = >[lang, readMeta(lang)])) as any;

// 平台裁剪
function pickCommon(m: any) {
return {
app_name: m.app_name,
};
}

function pickIOS(m: any) {
return {
CFBundleDisplayName: m.CFBundleDisplayName,
NSContactsUsageDescription: m.NSContactsUsageDescription,
};
}

const commonLocales = Object.fromEntries(LANGS.map((lang) = >[lang, pickCommon(meta[lang])]));

const iosLocales = Object.fromEntries(LANGS.map((lang) = >[lang, pickIOS(meta[lang])]));

export
default() = >({...baseConfig,
expo: {...baseConfig.expo,

// 覆盖 locales(Android-safe)
locales: commonLocales,

ios: {...baseConfig.expo.ios,

// iOS only
locales: iosLocales,

// fallback(必须)
infoPlist: {...pickIOS(meta['zh-Hans']),
},
},
},
});

:app.json没有直接起作用的配置方法,只有放弃。