Skip to content

Instantly share code, notes, and snippets.

@shichen85
Created March 25, 2023 23:34
Show Gist options
  • Save shichen85/ab1d96fac2a2d8c25b735dc392718611 to your computer and use it in GitHub Desktop.
Save shichen85/ab1d96fac2a2d8c25b735dc392718611 to your computer and use it in GitHub Desktop.
Use npm XCode to add localization metadata to an iOS project generated by GameMaker.
import { dirname, basename, join } from 'path';
import fs from 'fs-extra';
//@ts-ignore
import xcode from 'xcode';
export async function addLocalizationWithXCode(
projectPath: string,
languages: L10nLang[],
) {
const languageFileRootDir = getLanguageFileRootDir(projectPath);
// No types available. See https://www.npmjs.com/package/xcode for API
const parsedProj = xcode.project(projectPath);
const gameLanguages = languages;
const englishFileName = join(
languageFileRootDir,
'en.lproj',
'InfoPlist.strings',
);
return new Promise((resolve, reject) => {
parsedProj.parse(function (err: any) {
if (err) {
return reject(err);
} else {
gameLanguages.forEach((language) => {
if (language != 'en-US') {
//GMS's xcodeproj has en-us by default
//For example, adding "zh-Hans" requires the presence of the file ".../demo/zh-Hans.lproj/InfoPlist.strings"
const xcodeLang = l10nToXcode(language);
const languageFileDir = `${xcodeLang.replace(
/"/g,
'',
)}.lproj/InfoPlist.strings`;
const languageFileDirAbsolute = join(
languageFileRootDir,
languageFileDir,
);
fs.ensureFileSync(languageFileDirAbsolute);
fs.copyFileSync(englishFileName, languageFileDirAbsolute);
const groupKey = parsedProj.findPBXVariantGroupKey({
name: 'InfoPlist.strings',
});
/**
*
* @param path {String}
* @param group {String} group key
* @param opt {Object} see pbxFile for avail options
* @returns {Object} file; see pbxFile
*/
parsedProj.addFile(languageFileDir, groupKey);
parsedProj.addKnownRegion(xcodeLang);
}
});
fs.writeFileSync(projectPath, parsedProj.writeSync());
return resolve(
`Successfully added localization for ${languages.join(',')}`,
);
}
});
});
}
const l10nToXcodeDic = {
'zh-CN': '"zh-Hans"',
'ru-RU': 'ru',
'es-XL': 'es',
'es-ES': '"es-419"',
'pt-BR': '"pt-BR"',
'de-DE': 'de',
'it-IT': 'it',
'fr-FR': 'fr',
'ja-JP': 'ja',
'ko-KR': 'ko',
'zh-TW': '"zh-Hant"',
'en-US': 'en',
};
export type L10nLang = keyof typeof l10nToXcodeDic;
function l10nToXcode(l10nLang: L10nLang) {
const xcodeLang = l10nToXcodeDic[l10nLang];
if (xcodeLang) {
return xcodeLang;
} else {
throw new Error(`${l10nLang} does not exist in the l10nToXcodeDic!`);
}
}
/**
* @desc ".../demo.xcodeproj/project.pbxproj" should return ".../demo/"
* @param projectPath
*/
function getLanguageFileRootDir(projectPath: string) {
const projectDir = dirname(projectPath);
const projectName = basename(projectDir, '.xcodeproj');
const languageFileRootDir = join(dirname(projectDir), projectName);
return languageFileRootDir;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment