From 4a028bec43bf095f65f1aceb2e7c7472f2390aaa Mon Sep 17 00:00:00 2001 From: Johnny Gu Date: Sun, 15 May 2022 20:52:27 +0800 Subject: [PATCH 1/5] feat: add migration command --- package.json | 3 +- src/migration.js | 71 +++++++++++++++++++++++++++++++++ src/migration/filehit.js | 67 +++++++++++++++++++++++++++++++ src/migration/reader/android.js | 43 ++++++++++++++++++++ src/migration/reader/ios.js | 40 +++++++++++++++++++ 5 files changed, 223 insertions(+), 1 deletion(-) create mode 100755 src/migration.js create mode 100644 src/migration/filehit.js create mode 100644 src/migration/reader/android.js create mode 100644 src/migration/reader/ios.js diff --git a/package.json b/package.json index 99e5d90..3eeda96 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "Tool for generating localization files for iOS and Android", "main": "./src/index.js", "bin": { - "mirrorrim": "./src/index.js" + "mirrorrim": "./src/index.js", + "migration": "./src/migration.js" }, "author": "Johnny Gu (https://github.com/jhonny-me)", "license": "MIT", diff --git a/src/migration.js b/src/migration.js new file mode 100755 index 0000000..00656fe --- /dev/null +++ b/src/migration.js @@ -0,0 +1,71 @@ +#!/usr/bin/env node + +const { Command } = require("commander"); +const { version } = require("../package.json"); +const filehit = require("./migration/filehit"); +const path = require("path"); +var XLSX = require("xlsx"); + +const DEFAULT_OPTIONS = { + // local + inputDir: "./", + + outputDir: "./", +}; + +const getOptions = async (argv) => { + let options = new Command() + .option( + "--output-dir ", + `output excel base directory, default: ${DEFAULT_OPTIONS.outputDir}` + ) + .option( + "--input-dir ", + `directory of all wording resources, default: ${DEFAULT_OPTIONS.inputDir}` + ) + .version(version) + .parse(argv); + + return { + ...DEFAULT_OPTIONS, + ...options._optionValues + }; +}; + +const run = async (argv) => { + const options = await getOptions(argv); + try { + if (options.inputDir) { + let rows = await filehit.hit(options.inputDir); + if (rows.length < 1) { + console.warn("Warning: No string files found in input directory"); + return + } + const sheet = XLSX.utils.json_to_sheet(rows); + const workbook = XLSX.utils.book_new(); + XLSX.utils.book_append_sheet(workbook, sheet, "DEFAULT"); + /* calculate column width */ + const keys = Object.keys(rows[0]); + const columnWidthes = keys.map(key => { + const width = rows.reduce((w, r) => Math.min(60, Math.max(w, r[key].length + 1)), 10); + return { wch: width } + }) + sheet["!cols"] = columnWidthes; + + const outputPath = path.join(options.outputDir, "strings.xlsx"); + XLSX.writeFile(workbook, outputPath); + console.log(`Success! Xlsx file generated at ${outputPath}`); + } else { + console.log('Error: To run this app, you need to specify the input directory of string resources'); + process.exit(); + } + } catch (err) { + console.log(err); + } +}; + +run(process.argv).catch((error) => { + console.log("\n"); + console.error(error); + process.exit(1); +}); diff --git a/src/migration/filehit.js b/src/migration/filehit.js new file mode 100644 index 0000000..0199bb4 --- /dev/null +++ b/src/migration/filehit.js @@ -0,0 +1,67 @@ +const fs = require('fs'); +const path = require('path'); +const ios = require('./reader/ios'); +const android = require('./reader/android'); +const R = require("ramda"); + +const sortByKey = R.sortBy(R.prop('KEY')); + +async function exists (path) { + try { + await fs.access(path) + return true + } catch { + return false + } +} + +const concat = (oldArray, newArray) => { + const oldKeys = oldArray.map(obj => obj.KEY); + const newKeys = newArray.map(obj => obj.KEY); + const concatedKeys = Array.from(new Set([...oldKeys, ...newKeys])); + const concatedArray = concatedKeys.map(key => { + let oldObj = oldArray.find(obj => obj.KEY === key); + let newObj = newArray.find(obj => obj.KEY === key); + return { + ...oldObj, + ...newObj + } + }); + return concatedArray; +} + +const filehit = async (inputDir) => { + let keyValues = []; + let iOSen = path.join(inputDir, "en.lproj/Localizable.strings"); + if (fs.existsSync(iOSen)) { + // parse ios en + console.log('found: ', iOSen) + keyValues = await ios.read(iOSen, 'EN'); + } + + let iOSzh = path.join(inputDir, "zh-Hans.lproj/Localizable.strings"); + if (fs.existsSync(iOSzh)) { + // parse ios zh + console.log('found: ', iOSzh) + keyValues = concat(keyValues, await ios.read(iOSzh, 'ZH')); + } + + let androidEn = path.join(inputDir, "values/strings.xml"); + if (fs.existsSync(androidEn)) { + // parse android en + console.log('found: ', androidEn) + keyValues = concat(keyValues, await android.read(androidEn, 'EN')); + } + + let androidZh = path.join(inputDir, "values-zh/strings.xml"); + if (fs.existsSync(androidZh)) { + // parse andoird zh + console.log('found: ', androidZh) + keyValues = concat(keyValues, await android.read(androidZh, 'ZH')); + } + return sortByKey(keyValues); +} + +module.exports = { + hit: filehit +} \ No newline at end of file diff --git a/src/migration/reader/android.js b/src/migration/reader/android.js new file mode 100644 index 0000000..b75c780 --- /dev/null +++ b/src/migration/reader/android.js @@ -0,0 +1,43 @@ +const events = require('events'); +const fs = require('fs'); +const readline = require('readline'); + +const read = async (filepath, languageKey) => { + try { + const rl = readline.createInterface({ + input: fs.createReadStream(filepath), + crlfDelay: Infinity + }); + let outputs = []; + rl.on('line', (line) => { + if (!line.endsWith("<\/string>")) { return } + const value = line.replace(/[\s]+/, "").replace("<\/string>", ""); + + const key = line.slice(line.indexOf("\"") + 1, line.indexOf("\">")); + + outputs.push({ + KEY: key, + [languageKey]: value + }); + }); + + await events.once(rl, 'close'); + return outputs; + } catch (err) { + console.error(err); + } +} + +const formatValue = (input) => { + var input = String(input) + var input = input.replace(/\\'/g, '\'') + input = input.replace(/&/g, '&') + input = input.replace(/\\"/g, '\"') + input = input.replace(/</g, '<') + input = input.replace(/>/g, '>') + return input +} + +module.exports = { + read +} \ No newline at end of file diff --git a/src/migration/reader/ios.js b/src/migration/reader/ios.js new file mode 100644 index 0000000..a6791b8 --- /dev/null +++ b/src/migration/reader/ios.js @@ -0,0 +1,40 @@ +const events = require('events'); +const fs = require('fs'); +const readline = require('readline'); + +const read = async (filepath, languageKey) => { + try { + const rl = readline.createInterface({ + input: fs.createReadStream(filepath), + crlfDelay: Infinity + }); + let outputs = []; + rl.on('line', (line) => { + const array = line.split(" = ", 2); + if (array.length < 2) { return } + const key = array[0].slice(1, -1); + const value = array[1].slice(1, -2); + + outputs.push({ + KEY: key, + [languageKey]: formatValue(value) + }); + }); + + await events.once(rl, 'close'); + return outputs; + } catch (err) { + console.error(err); + } +} + +const formatValue = (input) => { + var input = String(input) + var input = input.replace(/\\"/g, '\"') + input = input.replace(/%@/g, '%s') + return input +} + +module.exports = { + read +} \ No newline at end of file From 2eb3fdc62e71dbbb892b5f97f8c25c3cf0cdae9e Mon Sep 17 00:00:00 2001 From: Johnny Gu Date: Sun, 15 May 2022 22:40:52 +0800 Subject: [PATCH 2/5] fix: wrong special character mapping --- src/migration/reader/android.js | 12 ++++++------ src/migration/reader/ios.js | 6 +++++- strings.xlsx | Bin 0 -> 16915 bytes 3 files changed, 11 insertions(+), 7 deletions(-) create mode 100644 strings.xlsx diff --git a/src/migration/reader/android.js b/src/migration/reader/android.js index b75c780..0c4d7bd 100644 --- a/src/migration/reader/android.js +++ b/src/migration/reader/android.js @@ -17,7 +17,7 @@ const read = async (filepath, languageKey) => { outputs.push({ KEY: key, - [languageKey]: value + [languageKey]: formatValue(value) }); }); @@ -30,11 +30,11 @@ const read = async (filepath, languageKey) => { const formatValue = (input) => { var input = String(input) - var input = input.replace(/\\'/g, '\'') - input = input.replace(/&/g, '&') - input = input.replace(/\\"/g, '\"') - input = input.replace(/</g, '<') - input = input.replace(/>/g, '>') + var input = input.replace(/\\\\'/g, '\'') + input = input.replace(/&amp;/g, '&') + input = input.replace(/\\\\"/g, '\"') + input = input.replace(/&lt;/g, '<') + input = input.replace(/&gt;/g, '>') return input } diff --git a/src/migration/reader/ios.js b/src/migration/reader/ios.js index a6791b8..4f01ab8 100644 --- a/src/migration/reader/ios.js +++ b/src/migration/reader/ios.js @@ -30,7 +30,11 @@ const read = async (filepath, languageKey) => { const formatValue = (input) => { var input = String(input) - var input = input.replace(/\\"/g, '\"') + var input = input.replace(/\\'/g, '\'') + input = input.replace(/&/g, '&') + input = input.replace(/\\\\"/g, '\"') + input = input.replace(/</g, '<') + input = input.replace(/>/g, '>') input = input.replace(/%@/g, '%s') return input } diff --git a/strings.xlsx b/strings.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..c716dad505382f841a4fbf0216b5d2cbd540497a GIT binary patch literal 16915 zcmeHP+ixUSTJNv{tp=@@2oMMf>8PdflC|6I+t|i-WVh{1GUFM`?o2KS4X3M4ch|UX zTUBklcR`w+UC_Y5-k1#wn?(zPU2eIcBw{3zKY|x{f`^^4hp?c$@Pgoh-*-;kPIYzr zG8Skd6Sb@AobPtN^L^j>&MjM)Kk?*GRg!;y^2C?!zxN}R3jKZ#g$H)+Mj-64w(kYI zEzjE>KXB}EDp`CMZ){Hlq2;+t)%y5El?m7IOv~*oRbOmwjLlV97;)F+w&#kaYF~ua zXO};9VR2j7JOWbKwfvBQiW@FfyHVsX)M}y86%G%_Jzuz}X?uagBYXy(n$L}0-VwFQ ziHX@7B*4NjKG6xiFLGDNF<C9Tv<{!6KQ$op{OaoJ z%zP}1A}WE@>+}Hp+{Enk%A^J_ffW4A0Q~goN~1BW!Al?oKRW=wadCcjT8EcFUE6YZ z2cW4#H#TDGDM;J1FO`DN0eo&E2G5{i4XJezi?-)R!)(prH@#p300c-e+GP=faGM*j z;s$qGfyIddUl2T3ql%1hpon;}&_wCcgq3cK^frD zYi~b#_wA!^e)+?{yjKFg67W_YylFWiWLL#L+x8r^O)5s0T(pAIVKlqk(lB@zv`a{@ zM_mo@YMaH~RB-t_>%qYUu5-c3!`oo>*JtP;+byN(99>3R057nCaCGV#i3xY=_% z<;;U#9&VfSy)xbn?rL4T-t!SP6Qk60-{=ZW%q^R{5mFFWM2zaZT_H+Z_ljj{dfl{) zzze;0#9p!3Dz{2i(zIHdA!SIHEC>D4FKaWpTGP$ub++o+WvyNldpaZ>g3Dw@xpV4b zO<`+le2(`b?v#;ia%4NXj=934Zkdof{lLh>t%nhMx+83lt(zhY%W$p*Xm5`8WsZ1N z+U=Wm-_aq1$l5KVd4+pk9&*jwZFITgm%;8>ZZ{A6e7Fk}f6j za&4J;J3|xiwq@HpG$+3j%G^7|0Ay~UknrTPibyA7eiyIg$zY(tbpkGNSl~r3Sy6YV z%V`0nE~k;5FecpzneSoEW9)-AKtusXB5_ zn=qOp0w-lQbulK2ww;AporF3ux4INf21Siq+GJ9(oR>r8Y12@cY7?0aLp}s8&thqd zSR)zZw!k7*G6zn&g|wQypK}+*tyT@`a#N@-(u#B1tjoSjOlY8e)I4P)r_*MtH7M

ueaaY+caZ>V6&PFCZI1+ljNCZ1wbDy>BUa-y4{m?13$FxE$SV)Ja z53H_{wq=zbTjNNRU(=Fss+`+?m&ehPR%a5AQ{d86QyJt}PCT@&RCd|8(>H}Y{=Ax! zH{<_jO`+icD+p62^?-rJ-GDRll%=W{L|qS2$nRRlMu2f&#tv8uR%lTTw*qNhEzj)7uXd;gTxE4MhapJY-4<6xky8xG86i7GmJ4cS1h79A2X30$0bT`J)oOCCL{ql= zI4V1V@Z~Bio%x(pWon{0vZKzRvgly6%3@7Hd4qa`=|F9scD>C$8i+rcmX z`;+%xeX>%a->1}ea40vqX*2ok8^Mys4sBPT{H#Oh2ZEdORDr%5EKf@;>>+TT?NEd1 z8C!wphu53flnY^>ZqM0pqL3M0&jnTLKvl%lgU(XS%vPB?iP7*(EC>9;XM0}six2Pr z*5U8msXe@Z7Z0Y&x?S}=`u*GL#c|a0@Xl|jmoQY%N8kH;j3d1v7GrsloI;a^3YHhc z&nc&`%dJ(zv%P@HK8z>Hv`ela8rUj`7pvRYxUl=GSmG(eR0YaG$r=;~`M|0J#e-A; z@**l&Uc@MbRNvje2MuoYPAXigx;We-o1oy1fyTJiuVdOM`AWhy!T{fv7nnFqlkW&s zw7h7GHkmE5x-LB<&&S`E7e$_f7t`V$&*e5=YY9gD0^(-4{R!K8J(>%x&BZv5iw`?I3(v%C7VyeNcnN}`Uv-eG5T0Lhzh1#mH7)x-3kroGwEpIQ{@oKlR;keMXH^g?J!f?Gc$AVmw{V1f;%w2Vc#6x!cDPID z$ygxT*k-9OsG|`w5Ms-0AN`fSv*bt`Rb+je)|0(>DZW=#n#o3VzoP4Ihf zpVDIr%?7=!pdIiHY@?!NZ~5~2D~q)~a?ZGZRj*&as#iDk>Q^tN)irQR*-_|I?9k{O zJFH9w(G71m#gag)I?%PtdUZpuKK#=U9{s_WQV@+VrEH2XRF>l_2dEnuClDS|OvPIV z#2KkTFpl5TA@kb!tAjUm@Q3$r9sc@XAHDvYPlpfh|3wa1lWIDZYFd*D8`$z}3T#&A zvZ}*9&v>{iOy>02Mu20IUDggP;hM~9v#wyawTp8gk;i=O^s_z76dvnfNDIf=CBZ^& znV(_bzxDb{mi7Hx-_{v5bVf&azV_koy@|h2@XUR%cd;RFI{`k?C|NPOt_YU9q>e2oCM|ZyR;MQ#b9DeH$AH8w!pWk}-qxXLsz@UKg zl$)lHnN%NeoLn#AsEN1{S&=PLJk>`!*rpW(UJzK$Guz|gzJ;R^Yr^q#l!lJ-;dfvA z@Q>b0K{RP*Q)!T?g^Bpvn=21*Z|L%pH{A_nD&KK$T2u;0%x zrPmZx38YSfD!;Wl*i#qgIyDtxDE~=gFYI_HB7l{U&f&@M6n<6@e6>6hXk^Dw3&X~* z+^T%x&L=7r`h8jr8~LM9M}QUjKX-~Bu8Y%4dgWHG;Xb!1lKRt0?X*C z1D`4pJ}?IlR-TlW*+vYzb`x2$2m)}Vq^IO5mV5@Ne~r? z$qmom>B31QAQn`3oF6GnSXvbn*^_C{5bL@mTt($@bQ?2Fs#$ zFX{z?z(~!7W@d8)rIFSy;Yj7cfN4Q5{)Dzrz>>x)__DpA}<# zZsy|HlrhzwnlL6N=Z&dflO3RF0U6!85O>cCbq`HhFzQ%{k?l3rZL&#iXvXG#NPA_J zyJhTa;GcXh(nl&Cl4L11@_wzY1TC}WwDBXF8yFN3pwxIBRx-{gC#ohLE?-zo^;~e; zyGG|~DZXDoX_w4>5bfkM zw!yXajg=R#G_f~IGigfq$Tt=&yvU>eG&@P~(#r}3eZO$?ssFfwiw*SqaRf;-!O`z0V05W|?lx+s90`Xeb+l8q1_h0|j zr(VSfLcgc-21YLac;krSFA$N8wHia~|QugE22K4!UetIeQAKm9tYuSX0BLl^bNU;V(a4S4bKs zAJ4VRa)y#)j5HA@N<0X&G<;}dGvHHcW_dB*`(f)8*VPR{^j($3DxuaaRS^M`kWiyq zjNv7CExH9Y6mQQp$DMFY93bZ!mp(rZ1RnIq9gbu7>n<(W0fg>SmDArFDHqY#=nWn>FRb8wI;+0RHa7fyT9@V#OYAs~5tRRCcWIxA9q}4&_6AsoVl=p^G`&_#eNM%# z;5FLhK6YGk(i8AkBYXbN?fD5pshy;Mj2v?BDSzemaYT^Bj$xSXM4qmbN2^_KZ;s-e zW~)guaXRjai4|rWC*la}l?nFaXtpG^9mN|4p5!Ty&APr%s?~r#fzo+=+@;Q#Xe)DasmH+9!7EdS^D~Ky~F8v literal 0 HcmV?d00001 From 4bfe5abb4b17f700f46a326a1e89318d28674a1e Mon Sep 17 00:00:00 2001 From: Johnny Gu Date: Sun, 15 May 2022 23:09:10 +0800 Subject: [PATCH 3/5] fix: remove breakline from value --- src/lib/android.js | 1 + src/lib/ios.js | 1 + strings.xlsx | Bin 16915 -> 212335 bytes 3 files changed, 2 insertions(+) diff --git a/src/lib/android.js b/src/lib/android.js index d1f4fa5..b7670bc 100644 --- a/src/lib/android.js +++ b/src/lib/android.js @@ -39,6 +39,7 @@ const generateFile = (data, basePath) => { const formatValue = (input) => { var input = String(input) var input = input.replace(/'/g, '\\\'') + input = input.replace(/(\r\n|\r|\n)/g, "") // remove breakline input = input.replace(/&/g, '&') input = input.replace(/"/g, '\\\"') input = input.replace(/ { const formatValue = (input) => { var input = String(input) var input = input.replace(/"/g, '\\\"') + input = input.replace(/(\r\n|\r|\n)/g, "") // remove breakline input = input.replace(/%s/g, '%@') return input } diff --git a/strings.xlsx b/strings.xlsx index c716dad505382f841a4fbf0216b5d2cbd540497a..7b0262f59d70e3b97ec2074f5c784e64d52aca48 100644 GIT binary patch literal 212335 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