update
This commit is contained in:
parent
5d348a23d1
commit
c8c30b39bf
@ -1,14 +1,20 @@
|
||||
t("aaaaa")
|
||||
// import {t } from "./languages"
|
||||
// import { nanoid } from "./nanoid"
|
||||
//const {t } = reuire("./languages")
|
||||
function output(){
|
||||
t("aaaaa")
|
||||
|
||||
t('aaaaa1')
|
||||
t("aaaaa2")
|
||||
t('aaaaa 3')
|
||||
t('aaaaa1')
|
||||
t("aaaaa2")
|
||||
t('aaaaa 3')
|
||||
|
||||
t('bbbbb',a,b,c)
|
||||
|
||||
t("cccc",()=>{},c)
|
||||
|
||||
|
||||
|
||||
t("ddddd中国",()=>{},c)
|
||||
t("eeeeee", )
|
||||
}
|
||||
|
||||
t('bbbbb',a,b,c)
|
||||
|
||||
t("cccc",()=>{},c)
|
||||
|
||||
|
||||
|
||||
t("ddddd中国",()=>{},c)
|
||||
t("eeeeee", )
|
@ -11,7 +11,9 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"art-template": "^4.13.2",
|
||||
"deepmerge": "^4.2.2",
|
||||
"glob": "^7.2.0",
|
||||
"gulp": "^4.0.2",
|
||||
"logsets": "^1.0.6",
|
||||
"readjson": "^2.2.2",
|
||||
|
193
pnpm-lock.yaml
generated
193
pnpm-lock.yaml
generated
@ -3,14 +3,18 @@ lockfileVersion: 5.3
|
||||
specifiers:
|
||||
'@babel/cli': ^7.17.6
|
||||
'@babel/core': ^7.17.5
|
||||
art-template: ^4.13.2
|
||||
deepmerge: ^4.2.2
|
||||
glob: ^7.2.0
|
||||
gulp: ^4.0.2
|
||||
logsets: ^1.0.6
|
||||
readjson: ^2.2.2
|
||||
through2: ^4.0.2
|
||||
|
||||
dependencies:
|
||||
art-template: 4.13.2
|
||||
deepmerge: 4.2.2
|
||||
glob: 7.2.0
|
||||
gulp: 4.0.2
|
||||
logsets: 1.0.6
|
||||
readjson: registry.npmmirror.com/readjson/2.2.2
|
||||
@ -267,6 +271,12 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/acorn/5.7.4:
|
||||
resolution: {integrity: sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/ansi-colors/1.1.0:
|
||||
resolution: {integrity: sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -393,6 +403,20 @@ packages:
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/art-template/4.13.2:
|
||||
resolution: {integrity: sha512-04ws5k+ndA5DghfheY4c8F1304XJKeTcaXqZCLpxFkNMSkaR3ChW1pX2i9d3sEEOZuLy7de8lFriRaik1jEeOQ==}
|
||||
engines: {node: '>= 1.0.0'}
|
||||
dependencies:
|
||||
acorn: 5.7.4
|
||||
escodegen: 1.14.3
|
||||
estraverse: 4.3.0
|
||||
html-minifier: 3.5.21
|
||||
is-keyword-js: 1.0.3
|
||||
js-tokens: 3.0.2
|
||||
merge-source-map: 1.1.0
|
||||
source-map: 0.5.7
|
||||
dev: false
|
||||
|
||||
/assign-symbols/1.0.0:
|
||||
resolution: {integrity: sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -548,6 +572,13 @@ packages:
|
||||
get-intrinsic: 1.1.1
|
||||
dev: false
|
||||
|
||||
/camel-case/3.0.0:
|
||||
resolution: {integrity: sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=}
|
||||
dependencies:
|
||||
no-case: 2.3.2
|
||||
upper-case: 1.1.3
|
||||
dev: false
|
||||
|
||||
/camelcase/3.0.0:
|
||||
resolution: {integrity: sha1-MvxLn82vhF/N9+c7uXysImHwqwo=}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -612,6 +643,13 @@ packages:
|
||||
static-extend: 0.1.2
|
||||
dev: false
|
||||
|
||||
/clean-css/4.2.4:
|
||||
resolution: {integrity: sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==}
|
||||
engines: {node: '>= 4.0'}
|
||||
dependencies:
|
||||
source-map: 0.6.1
|
||||
dev: false
|
||||
|
||||
/cliui/3.2.0:
|
||||
resolution: {integrity: sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=}
|
||||
dependencies:
|
||||
@ -679,6 +717,14 @@ packages:
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/commander/2.17.1:
|
||||
resolution: {integrity: sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==}
|
||||
dev: false
|
||||
|
||||
/commander/2.19.0:
|
||||
resolution: {integrity: sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==}
|
||||
dev: false
|
||||
|
||||
/commander/4.1.1:
|
||||
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
|
||||
engines: {node: '>= 6'}
|
||||
@ -757,6 +803,10 @@ packages:
|
||||
engines: {node: '>=0.10'}
|
||||
dev: false
|
||||
|
||||
/deep-is/0.1.4:
|
||||
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
|
||||
dev: false
|
||||
|
||||
/deepmerge/4.2.2:
|
||||
resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -882,6 +932,35 @@ packages:
|
||||
engines: {node: '>=0.8.0'}
|
||||
dev: true
|
||||
|
||||
/escodegen/1.14.3:
|
||||
resolution: {integrity: sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==}
|
||||
engines: {node: '>=4.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
esprima: 4.0.1
|
||||
estraverse: 4.3.0
|
||||
esutils: 2.0.3
|
||||
optionator: 0.8.3
|
||||
optionalDependencies:
|
||||
source-map: 0.6.1
|
||||
dev: false
|
||||
|
||||
/esprima/4.0.1:
|
||||
resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
|
||||
engines: {node: '>=4'}
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/estraverse/4.3.0:
|
||||
resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==}
|
||||
engines: {node: '>=4.0'}
|
||||
dev: false
|
||||
|
||||
/esutils/2.0.3:
|
||||
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/expand-brackets/2.1.4:
|
||||
resolution: {integrity: sha1-t3c14xXOMPa27/D4OwQVGiJEliI=}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -955,6 +1034,10 @@ packages:
|
||||
resolution: {integrity: sha1-5qdUzI8V5YmHqpy9J69m/W9OWvk=}
|
||||
dev: false
|
||||
|
||||
/fast-levenshtein/2.0.6:
|
||||
resolution: {integrity: sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=}
|
||||
dev: false
|
||||
|
||||
/file-uri-to-path/1.0.0:
|
||||
resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==}
|
||||
requiresBuild: true
|
||||
@ -1291,6 +1374,11 @@ packages:
|
||||
function-bind: 1.1.1
|
||||
dev: false
|
||||
|
||||
/he/1.2.0:
|
||||
resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/homedir-polyfill/1.0.3:
|
||||
resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -1302,6 +1390,20 @@ packages:
|
||||
resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
|
||||
dev: false
|
||||
|
||||
/html-minifier/3.5.21:
|
||||
resolution: {integrity: sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==}
|
||||
engines: {node: '>=4'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
camel-case: 3.0.0
|
||||
clean-css: 4.2.4
|
||||
commander: 2.17.1
|
||||
he: 1.2.0
|
||||
param-case: 2.1.1
|
||||
relateurl: 0.2.7
|
||||
uglify-js: 3.4.10
|
||||
dev: false
|
||||
|
||||
/inflight/1.0.6:
|
||||
resolution: {integrity: sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=}
|
||||
dependencies:
|
||||
@ -1444,6 +1546,11 @@ packages:
|
||||
dependencies:
|
||||
is-extglob: 2.1.1
|
||||
|
||||
/is-keyword-js/1.0.3:
|
||||
resolution: {integrity: sha1-rDDc81tnH0snsX9ctXI1EmAhEy0=}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/is-negated-glob/1.0.0:
|
||||
resolution: {integrity: sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -1527,6 +1634,10 @@ packages:
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/js-tokens/3.0.2:
|
||||
resolution: {integrity: sha1-mGbfOVECEw449/mWvOtlRDIJwls=}
|
||||
dev: false
|
||||
|
||||
/js-tokens/4.0.0:
|
||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
||||
dev: true
|
||||
@ -1606,6 +1717,14 @@ packages:
|
||||
flush-write-stream: 1.1.1
|
||||
dev: false
|
||||
|
||||
/levn/0.3.0:
|
||||
resolution: {integrity: sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
dependencies:
|
||||
prelude-ls: 1.1.2
|
||||
type-check: 0.3.2
|
||||
dev: false
|
||||
|
||||
/liftoff/3.1.0:
|
||||
resolution: {integrity: sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==}
|
||||
engines: {node: '>= 0.8'}
|
||||
@ -1640,6 +1759,10 @@ packages:
|
||||
deepmerge: registry.npmmirror.com/deepmerge/4.2.2
|
||||
dev: false
|
||||
|
||||
/lower-case/1.1.4:
|
||||
resolution: {integrity: sha1-miyr0bno4K6ZOkv31YdcOcQujqw=}
|
||||
dev: false
|
||||
|
||||
/make-dir/2.1.0:
|
||||
resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==}
|
||||
engines: {node: '>=6'}
|
||||
@ -1677,6 +1800,12 @@ packages:
|
||||
stack-trace: 0.0.10
|
||||
dev: false
|
||||
|
||||
/merge-source-map/1.1.0:
|
||||
resolution: {integrity: sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==}
|
||||
dependencies:
|
||||
source-map: 0.6.1
|
||||
dev: false
|
||||
|
||||
/micromatch/3.1.10:
|
||||
resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -1753,6 +1882,12 @@ packages:
|
||||
resolution: {integrity: sha1-yobR/ogoFpsBICCOPchCS524NCw=}
|
||||
dev: false
|
||||
|
||||
/no-case/2.3.2:
|
||||
resolution: {integrity: sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==}
|
||||
dependencies:
|
||||
lower-case: 1.1.4
|
||||
dev: false
|
||||
|
||||
/node-releases/2.0.2:
|
||||
resolution: {integrity: sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==}
|
||||
dev: true
|
||||
@ -1858,6 +1993,18 @@ packages:
|
||||
dependencies:
|
||||
wrappy: 1.0.2
|
||||
|
||||
/optionator/0.8.3:
|
||||
resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
dependencies:
|
||||
deep-is: 0.1.4
|
||||
fast-levenshtein: 2.0.6
|
||||
levn: 0.3.0
|
||||
prelude-ls: 1.1.2
|
||||
type-check: 0.3.2
|
||||
word-wrap: 1.2.3
|
||||
dev: false
|
||||
|
||||
/ordered-read-streams/1.0.1:
|
||||
resolution: {integrity: sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=}
|
||||
dependencies:
|
||||
@ -1871,6 +2018,12 @@ packages:
|
||||
lcid: 1.0.0
|
||||
dev: false
|
||||
|
||||
/param-case/2.1.1:
|
||||
resolution: {integrity: sha1-35T9jPZTHs915r75oIWPvHK+Ikc=}
|
||||
dependencies:
|
||||
no-case: 2.3.2
|
||||
dev: false
|
||||
|
||||
/parse-filepath/1.0.2:
|
||||
resolution: {integrity: sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=}
|
||||
engines: {node: '>=0.8'}
|
||||
@ -1979,6 +2132,11 @@ packages:
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/prelude-ls/1.1.2:
|
||||
resolution: {integrity: sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
dev: false
|
||||
|
||||
/pretty-hrtime/1.0.3:
|
||||
resolution: {integrity: sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=}
|
||||
engines: {node: '>= 0.8'}
|
||||
@ -2073,6 +2231,11 @@ packages:
|
||||
safe-regex: 1.1.0
|
||||
dev: false
|
||||
|
||||
/relateurl/0.2.7:
|
||||
resolution: {integrity: sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=}
|
||||
engines: {node: '>= 0.10'}
|
||||
dev: false
|
||||
|
||||
/remove-bom-buffer/3.0.0:
|
||||
resolution: {integrity: sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -2259,6 +2422,11 @@ packages:
|
||||
resolution: {integrity: sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
/source-map/0.6.1:
|
||||
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/sparkles/1.0.1:
|
||||
resolution: {integrity: sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==}
|
||||
engines: {node: '>= 0.10'}
|
||||
@ -2439,6 +2607,13 @@ packages:
|
||||
through2: 2.0.5
|
||||
dev: false
|
||||
|
||||
/type-check/0.3.2:
|
||||
resolution: {integrity: sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
dependencies:
|
||||
prelude-ls: 1.1.2
|
||||
dev: false
|
||||
|
||||
/type/1.2.0:
|
||||
resolution: {integrity: sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==}
|
||||
dev: false
|
||||
@ -2451,6 +2626,15 @@ packages:
|
||||
resolution: {integrity: sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=}
|
||||
dev: false
|
||||
|
||||
/uglify-js/3.4.10:
|
||||
resolution: {integrity: sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==}
|
||||
engines: {node: '>=0.8.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
commander: 2.19.0
|
||||
source-map: 0.6.1
|
||||
dev: false
|
||||
|
||||
/unc-path-regex/0.1.2:
|
||||
resolution: {integrity: sha1-5z3T17DXxe2G+6xrCufYxqadUPo=}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -2507,6 +2691,10 @@ packages:
|
||||
engines: {node: '>=4'}
|
||||
dev: false
|
||||
|
||||
/upper-case/1.1.3:
|
||||
resolution: {integrity: sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=}
|
||||
dev: false
|
||||
|
||||
/urix/0.1.0:
|
||||
resolution: {integrity: sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=}
|
||||
deprecated: Please see https://github.com/lydell/urix#deprecated
|
||||
@ -2599,6 +2787,11 @@ packages:
|
||||
isexe: 2.0.0
|
||||
dev: false
|
||||
|
||||
/word-wrap/1.2.3:
|
||||
resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/wrap-ansi/2.1.0:
|
||||
resolution: {integrity: sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
14
readme.md
14
readme.md
@ -170,14 +170,9 @@ t("今天是{date}",{date:new Date()})
|
||||
|
||||
```javascript
|
||||
|
||||
import { injectLanguage } from "voerka-i18n"
|
||||
import mylinLang from "mylib/languages"
|
||||
|
||||
// 在当前工程注入第三方库的语言文件
|
||||
injectLanguage(mylinLang)
|
||||
|
||||
import t from "./languages"
|
||||
|
||||
import i18n from "voerka-i18n"
|
||||
import { t } from "./languages"
|
||||
|
||||
t("xxxxx")
|
||||
|
||||
VoerkaI18n实例
|
||||
@ -195,3 +190,6 @@ messages:{
|
||||
```
|
||||
|
||||
|
||||
## 一语多译
|
||||
|
||||
一语多译指同一句文本在不同的语景下,需要翻译成不同的内容。比如
|
@ -2,6 +2,7 @@
|
||||
* 转译源码中的t翻译函数的翻译内容转换为唯一的id值
|
||||
*
|
||||
* - 将源文件中的t("xxxxx")转码成t(hash(xxxxx))
|
||||
* - 自动导入languages/index.js中的翻译函数t
|
||||
*
|
||||
* 使用方法:
|
||||
*
|
||||
@ -18,12 +19,81 @@
|
||||
|
||||
const { getMessageId } = require('./utils');
|
||||
const TRANSLATE_FUNCTION_NAME = "t"
|
||||
const fs = require("fs");
|
||||
|
||||
const DefaultI18nPluginOptions = {
|
||||
translateFunctionName:"t", // 默认的翻译函数名称
|
||||
location:"./languages" // 默认的翻译文件存放的目录,即编译后的语言文件的文件夹
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前是否是一个esmodule,判断依据是
|
||||
* - 包含import语句
|
||||
* - 包含export语句
|
||||
|
||||
* @param {*} path
|
||||
*/
|
||||
function isEsModule(path){
|
||||
for(let ele of path.node.body){
|
||||
if(ele.type==="ImportDeclaration" || ele.type==="ExportNamedDeclaration" || ele.type==="ExportDefaultDeclaration"){
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否导入了翻译函数
|
||||
* import { t } from "./i18n"
|
||||
* const { t } form "./languages"
|
||||
* @param {*} path
|
||||
* @returns
|
||||
*/
|
||||
function hasImportTranslateFunction(path){
|
||||
for(let ele of path.node.body){
|
||||
if(ele.type==="ImportDeclaration"){
|
||||
if(ele.specifiers.findIndex(s => s.type === "ImportSpecifier" && s.imported.name ==TRANSLATE_FUNCTION_NAME && s.local.name===TRANSLATE_FUNCTION_NAME)>-1){
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function hasRequireTranslateFunction(path){
|
||||
for(let ele of path.node.body){
|
||||
if(ele.type==="VariableDeclaration"){
|
||||
if(ele.specifiers.findIndex(s => s.type === "ImportSpecifier" && s.imported.name ==TRANSLATE_FUNCTION_NAME && s.local.name===TRANSLATE_FUNCTION_NAME)>-1){
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
module.exports = function voerkai18nPlugin(babel) {
|
||||
const t = babel.types;
|
||||
const pluginOptions = Object.assign({},DefaultI18nPluginOptions);
|
||||
return {
|
||||
visitor:{
|
||||
Program(path, state){
|
||||
Object.assign(pluginOptions,state.opts || {});
|
||||
const { location = "./languages", translateFunctionName } = pluginOptions
|
||||
if(isEsModule(path)){
|
||||
// 如果没有定义t函数,则自动导入
|
||||
if(!hasImportTranslateFunction(path)){
|
||||
path.node.body.unshift(t.importDeclaration([
|
||||
t.ImportSpecifier(t.identifier(translateFunctionName),t.identifier(translateFunctionName)
|
||||
)],t.stringLiteral(location)))
|
||||
}
|
||||
}else{
|
||||
if(!hasRequireTranslateFunction(path)){
|
||||
path.node.body.unshift(t.variableDeclaration("const",[
|
||||
t.variableDeclarator(
|
||||
t.ObjectPattern([t.ObjectProperty(t.Identifier(translateFunctionName),t.Identifier(translateFunctionName),false,true)]),
|
||||
t.CallExpression(t.Identifier("require"),[t.stringLiteral(location)])
|
||||
)
|
||||
]))
|
||||
}
|
||||
}
|
||||
},
|
||||
CallExpression(path,state){
|
||||
let options = state.opts
|
||||
// 只对翻译函数进行转码
|
||||
if(path.node.callee.name===TRANSLATE_FUNCTION_NAME){
|
||||
if(path.node.arguments.length>0 && t.isStringLiteral(path.node.arguments[0])){
|
||||
|
@ -9,7 +9,9 @@ babel.transform(code, {
|
||||
plugins: [
|
||||
[
|
||||
i18nPlugin,
|
||||
{a:1,b:2}
|
||||
{
|
||||
location:"./languages" // 指定语言文件存放的目录,即保存编译后的语言文件的文件夹
|
||||
}
|
||||
]]
|
||||
}, function(err, result) {
|
||||
console.log(result.code)
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
* 编译输出:
|
||||
*
|
||||
* hashId = hash([projectName]_[namespace]_[message])
|
||||
* hashId = getMessageId()
|
||||
*
|
||||
* - languages/index.js 主源码,用来引用语言文件
|
||||
* {
|
||||
@ -36,15 +36,73 @@
|
||||
* @param {*} opts
|
||||
*/
|
||||
|
||||
const readJson = require("readjson")
|
||||
const glob = require("glob")
|
||||
const createLogger = require("logsets")
|
||||
const path = require("path")
|
||||
const { getMessageId } = require("./utils")
|
||||
const fs = require("fs")
|
||||
const logger = createLogger()
|
||||
const artTemplate = require("art-template")
|
||||
|
||||
function normalizeCompileOptions(opts={}) {
|
||||
let options = Object.assign({
|
||||
input:null, // 指定要编译的文件夹,即extract输出的语言文件夹
|
||||
output:null, // 指定编译后的语言文件夹,如果没有指定,则使用input目录
|
||||
formatters:{}, // 对插值变量进行格式化的函数清单
|
||||
formatters:{}, // 对插值变量进行格式化的函数列表
|
||||
}, opts)
|
||||
return opts;
|
||||
}
|
||||
|
||||
module.exports = function compile(opts={}){
|
||||
module.exports = function compile(langFolder,opts={}){
|
||||
let options = normalizeCompileOptions(opts);
|
||||
let { output } = options;
|
||||
|
||||
//1. 加载多语言配置文件
|
||||
import(`file:///${path.join(langFolder,"settings.js")}`).then(module=>{
|
||||
let { languages,defaultLanguage,activeLanguage,namespaces } = module.default;
|
||||
|
||||
// 1. 合并生成最终的语言文件
|
||||
let messages = {} ,msgId =1
|
||||
glob.sync(path.join(langFolder,"translates/*.json")).forEach(file=>{
|
||||
try{
|
||||
let msg = readJson.sync(file)
|
||||
Object.entries(msg).forEach(([msg,langs])=>{
|
||||
if(msg in messages){
|
||||
Object.assign(messages[msg],langs)
|
||||
}else{
|
||||
messages[msg] = langs
|
||||
}
|
||||
})
|
||||
}catch(e){
|
||||
logger.log("读取语言文件{}失败:{}",file,e.message)
|
||||
}
|
||||
})
|
||||
// 2. 为每一个文本内容生成一个唯一的id
|
||||
let messageIds = {}
|
||||
Object.entries(messages).forEach(([msg,langs])=>{
|
||||
langs.$id = msgId++
|
||||
messageIds[msg] = langs.$id
|
||||
})
|
||||
// 3. 为每一个语言生成对应的语言文件
|
||||
languages.forEach(lang=>{
|
||||
let langMessages = {}
|
||||
Object.entries(messages).forEach(([message,translatedMsgs])=>{
|
||||
langMessages[translatedMsgs.$id] = lang.name in translatedMsgs ? translatedMsgs[lang.name] : message
|
||||
})
|
||||
// 为每一种语言生成一个语言文件
|
||||
fs.writeFileSync(path.join(langFolder,`${lang.name}.js`),`export default ${JSON.stringify(langMessages,null,4)}`)
|
||||
})
|
||||
|
||||
// 4. 生成id映射文件
|
||||
fs.writeFileSync(path.join(langFolder,"messageIds.js"),`export default ${JSON.stringify(messageIds,null,4)}`)
|
||||
|
||||
const hasFormatters = fs.existsSync(path.join(langFolder,"formatters.js"))
|
||||
// 生成编译后的访问入口文件
|
||||
const entryContent = artTemplate(path.join(__dirname,"entry.template.js"), {languages,defaultLanguage,activeLanguage,namespaces } )
|
||||
fs.writeFileSync(path.join(langFolder,"index.js"),entryContent)
|
||||
|
||||
})
|
||||
|
||||
|
||||
}
|
7
src/compile.test.js
Normal file
7
src/compile.test.js
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
|
||||
const compile = require('./compile');
|
||||
const path = require("path")
|
||||
|
||||
|
||||
compile(path.resolve(__dirname,"../demodata/languages"))
|
56
src/entry.template.js
Normal file
56
src/entry.template.js
Normal file
@ -0,0 +1,56 @@
|
||||
import messageIds from "./messageIds"
|
||||
import { translate,i18n } from "voerka-i18n"
|
||||
import defaultMessages from "./{{defaultLanguage}}.js"
|
||||
import i18nSettings from "./settings.js"
|
||||
import formatters from "voerka-i18n/formatters"
|
||||
|
||||
// 自动创建全局VoerkaI18n实例
|
||||
if(!globalThis.VoerkaI18n){
|
||||
globalThis.VoerkaI18n = new i18n(i18nSettings)
|
||||
}
|
||||
|
||||
let scopeContext = {
|
||||
messages : defaultMessages, // 当前语言的消息
|
||||
ids:messageIds,
|
||||
formatters:{
|
||||
...formatters,
|
||||
...i18nSettings.formatters || {}
|
||||
},
|
||||
languageLoaders:{}
|
||||
}
|
||||
|
||||
let supportedlanguages = {}
|
||||
|
||||
messages["{{defaultLanguage}}"]= defaultMessages
|
||||
{{each languages}}{{if $value.name !== defaultLanguage}}
|
||||
scopeContext.languageLoaders["{{$value.name}}"] = ()=>import("./{{$value.name}}.js")
|
||||
{{/if}}{{/each}}
|
||||
|
||||
const t = ()=> translate.bind(scopeContext)(...arguments)
|
||||
|
||||
|
||||
// 侦听语言切换事件
|
||||
VoerkaI18n.on(async function(lang)=>{
|
||||
|
||||
if(lang === defaultLanguage){
|
||||
scopeContext.messages = defaultMessages
|
||||
return
|
||||
}
|
||||
const loader = scopeContext.languageLoaders[lang]
|
||||
|
||||
if(typeof(loader) === "function"){
|
||||
try{
|
||||
scopeContext.messages = await loader()
|
||||
}catch(e){
|
||||
console.warn(`Error loading language ${lang} : ${e.message}`)
|
||||
scopeContext.messages = defaultMessages
|
||||
}
|
||||
}else if(typeof(loader) === "object"){
|
||||
scopeContext.messages = loader
|
||||
}else{
|
||||
scopeContext.messages = defaultMessages
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
export t
|
@ -67,7 +67,7 @@ function extractTranslateTextUseRegexp(content,namespace,extractor,file,options)
|
||||
texts[ns][text] ={}
|
||||
languages.forEach(language=>{
|
||||
if(language.name !== defaultLanguage){
|
||||
texts[ns][text][language.name] = ""
|
||||
texts[ns][text][language.name] = text //""
|
||||
}
|
||||
})
|
||||
texts[ns][text]["$file"]=[file.relative]
|
||||
@ -388,7 +388,7 @@ module.exports = function(options={}){
|
||||
}
|
||||
}
|
||||
// 将元数据生成到 i18n.meta.json
|
||||
const metaFile = path.join(outputPath,"i18n.settings.js")
|
||||
const metaFile = path.join(outputPath,"settings.js")
|
||||
const meta = {
|
||||
languages : options.languages,
|
||||
defaultLanguage: options.defaultLanguage,
|
||||
|
352
src/index.js
352
src/index.js
@ -1,52 +1,223 @@
|
||||
import deepMerge from "deepmerge"
|
||||
|
||||
|
||||
let ParamRegExp=/\{\w*\}/g
|
||||
//添加一个params参数,使字符串可以进行变量插值替换,
|
||||
// "this is {a}+{b}".params({a:1,b:2}) --> this is 1+2
|
||||
// "this is {a}+{b}".params(1,2) --> this is 1+2
|
||||
// "this is {}+{}".params([1,2]) --> this is 1+2
|
||||
if(!String.prototype.hasOwnProperty("params")){
|
||||
// 用来提取字符里面的插值变量参数
|
||||
// let varRegexp = /\{\s*(?<var>\w*\.?\w*)\s*\}/g
|
||||
let varRegexp = /\{\s*((?<varname>\w+)?(\s*\|\s*(?<formatter>\w*))?)?\s*\}/g
|
||||
// 插值变量字符串替换正则
|
||||
//let varReplaceRegexp =String.raw`\{\s*(?<var>{name}\.?\w*)\s*\}`
|
||||
|
||||
String.prototype.params=function (params) {
|
||||
let result=this.valueOf()
|
||||
if(typeof params === "object"){
|
||||
for(let name in params){
|
||||
result=result.replace("{"+ name +"}",params[name])
|
||||
}
|
||||
|
||||
let varReplaceRegexp =String.raw`\{\s*{varname}\s*\}`
|
||||
|
||||
/**
|
||||
* 考虑到通过正则表达式进行插件的替换可能较慢,因此提供一个简单方法来过滤掉那些
|
||||
* 不需要进行插值处理的字符串
|
||||
* 原理很简单,就是判断一下是否同时具有{和}字符,如果有则认为可能有插值变量,如果没有则一定没有插件变量,则就不需要进行正则匹配
|
||||
* 从而可以减少不要的正则匹配
|
||||
* 注意:该方法只能快速判断一个字符串不包括插值变量
|
||||
* @param {*} str
|
||||
* @returns {boolean} true=可能包含插值变量,
|
||||
*/
|
||||
function hasInterpolation(str){
|
||||
return str.includes("{") && str.includes("}")
|
||||
}
|
||||
/**
|
||||
* 获取指定变量类型名称
|
||||
* getDataTypeName(1) == Number
|
||||
* getDataTypeName("") == String
|
||||
* getDataTypeName(null) == Null
|
||||
* getDataTypeName(undefined) == Undefined
|
||||
* getDataTypeName(new Date()) == Date
|
||||
* getDataTypeName(new Error()) == Error
|
||||
*
|
||||
* @param {*} v
|
||||
* @returns
|
||||
*/
|
||||
function getDataTypeName(v){
|
||||
if (v === null) return 'Null'
|
||||
if (v === undefined) return 'Undefined'
|
||||
if(typeof(v)==="function") return "Function"
|
||||
return v.constructor && v.constructor.name;
|
||||
};
|
||||
|
||||
/**
|
||||
* 提取字符串中的插值变量
|
||||
* @param {*} str
|
||||
* @returns {Array} 变量名称列表
|
||||
*/
|
||||
function getInterpolatedVars(str){
|
||||
let result = []
|
||||
let match
|
||||
while ((match = varRegexp.exec(str)) !== null) {
|
||||
if (match.index === varRegexp.lastIndex) {
|
||||
varRegexp.lastIndex++;
|
||||
}
|
||||
if(match.groups.varname) {
|
||||
result.push(match.groups.formatter ? match.groups.varname+"|"+match.groups.formatter : match.groups.varname)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
/**
|
||||
* 将要翻译内容提供了一个非文本内容时进行默认的转换
|
||||
* - 对函数则执行并取返回结果()
|
||||
* - 对Array和Object使用JSON.stringify
|
||||
* - 其他类型使用toString
|
||||
*
|
||||
* @param {*} value
|
||||
* @returns
|
||||
*/
|
||||
function transformVarValue(value){
|
||||
let result = value
|
||||
if(typeof(result)==="function") result = value()
|
||||
if(!(typeof(result)==="string")){
|
||||
if(Array.isArray(result) || typeof(result)==="object"){
|
||||
result = JSON.stringify(result)
|
||||
}else{
|
||||
let i=0
|
||||
for(let match of result.match(ParamRegExp) || []){
|
||||
if(i<arguments.length){
|
||||
result=result.replace(match,arguments[i])
|
||||
i+=1
|
||||
}
|
||||
result = result.toString()
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
/**
|
||||
* 字符串可以进行变量插值替换,
|
||||
* replaceInterpolateVars("<模板字符串>",{变量名称:变量值,变量名称:变量值,...})
|
||||
* replaceInterpolateVars("<模板字符串>",[变量值,变量值,...])
|
||||
* replaceInterpolateVars("<模板字符串>",变量值,变量值,...])
|
||||
*
|
||||
- 当只有两个参数并且第2个参数是{}时,将第2个参数视为命名变量的字典
|
||||
replaceInterpolateVars("this is {a}+{b},{a:1,b:2}) --> this is 1+2
|
||||
- 当只有两个参数并且第2个参数是[]时,将第2个参数视为位置参数
|
||||
replaceInterpolateVars"this is {}+{}",[1,2]) --> this is 1+2
|
||||
- 普通位置参数替换
|
||||
replaceInterpolateVars("this is {a}+{b}",1,2) --> this is 1+2
|
||||
-
|
||||
|
||||
* @param {*} template
|
||||
* @returns
|
||||
*/
|
||||
function replaceInterpolateVars(template,...args) {
|
||||
let result=template
|
||||
if(!hasInterpolation(template)) return
|
||||
if(args.length===1 && typeof(args[0]) === "object" && !Array.isArray(args[0])){ // 变量插值
|
||||
for(let name in args[0]){
|
||||
// 如果变量中包括|管道符,则需要进行转换以适配更宽松的写法,比如data|time能匹配"data |time","data | time"等
|
||||
let nameRegexp = name.includes("|") ? name.split("|").join("\\s*\\|\\s*") : name
|
||||
result=result.replaceAll(new RegExp(varReplaceRegexp.replaceAll("{varname}",nameRegexp),"g"),transformVarValue(args[0][name]))
|
||||
}
|
||||
}else{ // 位置插值
|
||||
const params=(args.length===1 && Array.isArray(args[0])) ? [...args[0]] : args
|
||||
let i=0
|
||||
for(let match of result.match(varRegexp) || []){
|
||||
if(i<params.length){
|
||||
let param = transformVarValue(params[i])
|
||||
result=result.replace(match,param)
|
||||
i+=1
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// 默认语言配置
|
||||
export const defaultLanguageSettings = {
|
||||
defaultLanguage: "cn",
|
||||
activeLanguage: "cn",
|
||||
languages:{
|
||||
cn:{name:"cn",title:"中文",default:true},
|
||||
en:{name:"en",title:"英文"},
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 翻译函数
|
||||
*
|
||||
* translate("要翻译的文本内容") 如果默认语言是中文,则不会进行翻译直接返回
|
||||
* translate("I am {} {}","man") == I am man 位置插值
|
||||
* translate("I am {p}",{p:"man"}) 字典插值
|
||||
* translate("I am {p}",{p:"man",ns:""}) 指定名称空间
|
||||
* translate("I am {p}",{p:"man",namespace:""})
|
||||
* translate("I am {p}",{p:"man",namespace:""})
|
||||
* translate("total {count} items", {count:1}) //复数形式
|
||||
* translate({count:1,plurals:'count'}) // 复数形式
|
||||
* translate("total {} {} {} items",a,b,c) // 位置变量插值
|
||||
*
|
||||
*/
|
||||
export function translate() {
|
||||
let content = arguments[0],options={}
|
||||
try{
|
||||
if(arguments.length === 2 && typeof(arguments[1])=='object'){
|
||||
Object.assign(options,arguments[1])
|
||||
}else if(arguments.length >= 2){
|
||||
options=[...arguments].splice(1)
|
||||
}
|
||||
// 默认语言是中文,不需要查询加载,只需要做插值变换即可
|
||||
if(this.language === this.defaultLanguage){
|
||||
return this._replaceVars(content,options)
|
||||
}else{
|
||||
let result = this.messages[this.language][content]
|
||||
if(content in this.messages[this.language]){
|
||||
// 复数形式,需要通过plurals来指定内容中包括的复数插值
|
||||
if(Array.isArray(result)){
|
||||
let plurals = options.plurals
|
||||
if(typeof(plurals) == 'string' && (plurals in options)){
|
||||
return options[plurals]>1 ? result[1].params(options) : result[0].params(options)
|
||||
}else{
|
||||
return this._replaceVars(result[0],options)
|
||||
}
|
||||
}else{
|
||||
return this._replaceVars(result,options);
|
||||
}
|
||||
}else{
|
||||
return this._replaceVars(result,options)
|
||||
}
|
||||
}
|
||||
}catch(e){
|
||||
return content
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class i18n{
|
||||
|
||||
/**
|
||||
* 多语言管理类
|
||||
*
|
||||
* 当导入编译后的多语言文件时(import("./languages")),会自动生成全局实例VoerkaI18n
|
||||
*
|
||||
* VoerkaI18n.languages // 返回支持的语言列表
|
||||
* VoerkaI18n.defaultLanguage // 默认语言
|
||||
* VoerkaI18n.language // 当前语言
|
||||
* VoerkaI18n.change(language) // 切换到新的语言
|
||||
*
|
||||
*
|
||||
* VoerkaI18n.on("change",(language)=>{}) // 注册语言切换事件
|
||||
* VoerkaI18n.off("change",(language)=>{})
|
||||
*
|
||||
* */
|
||||
export class I18n{
|
||||
static instance = null; // 单例引用
|
||||
_language = "cn" // 当前语言
|
||||
defaultLanguage = "cn"
|
||||
supportedLanguages = ["cn","en"] // 支持的语言
|
||||
builtInLanguages = ["cn","en"] // 内置语言
|
||||
messages = {}
|
||||
callbacks = [] // 当切换语言时的回调事件
|
||||
constructor(){
|
||||
callbacks = [] // 当切换语言时的回调事件
|
||||
constructor(settings={}){
|
||||
if(i18n.instance==null){
|
||||
this.reset()
|
||||
i18n.instance = this;
|
||||
}
|
||||
this._settings = deepMerge(defaultLanguageSettings,settings)
|
||||
this._scopes=[] // [{cn:{...},en:Promise,de:Promise},{...},{...}]
|
||||
return i18n.instance;
|
||||
}
|
||||
addListener(callback){
|
||||
// 当前激活语言
|
||||
get language(){return this._settings.activeLanguage}
|
||||
// 默认语言
|
||||
get defaultLanguage(){return this.this._settings.defaultLanguage}
|
||||
// 支持的语言列表
|
||||
get languages(){return this._settings.languages}
|
||||
|
||||
on(callback){
|
||||
this.callbacks.push(callback)
|
||||
}
|
||||
removeListener(callback){
|
||||
off(callback){
|
||||
for(let i=0;i<this.callbacks.length;i++){
|
||||
if(this.callbacks[i]===callback ){
|
||||
this.callbacks.splice(i,1)
|
||||
@ -54,7 +225,7 @@ class i18n{
|
||||
}
|
||||
}
|
||||
}
|
||||
removeAllListeners(){
|
||||
offAll(){
|
||||
this.callbacks=[]
|
||||
}
|
||||
_triggerCallback(){
|
||||
@ -63,95 +234,46 @@ class i18n{
|
||||
callback.call(this,this.language)
|
||||
}
|
||||
})
|
||||
}
|
||||
get language(){
|
||||
return this._language
|
||||
}
|
||||
set language(value){
|
||||
if(value in this.supportedLanguages){
|
||||
this._language = value
|
||||
}
|
||||
/**
|
||||
* 切换语言
|
||||
*/
|
||||
async change(value){
|
||||
if(value in this.languages){
|
||||
//
|
||||
let asyncMsgLoaders = this._scopes.map(scope=>scope[value]).filter(loader=>{
|
||||
loader!=null}
|
||||
)
|
||||
// 加载所有
|
||||
if(asyncMsgLoaders.length>0){
|
||||
await Promise.all(asyncMsgLoaders)
|
||||
}
|
||||
|
||||
this._settings.activeLanguage = value
|
||||
this._triggerCallback()
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 当配置更新时调用此方法
|
||||
*/
|
||||
reset(){
|
||||
|
||||
let settings = {
|
||||
current:"cn",
|
||||
default:"cn",
|
||||
supportedLanguages:["en","cn"]
|
||||
}
|
||||
if(VoerkaSettings!==undefined) Object.assign(settings,VoerkaSettings.get("i18n") )
|
||||
|
||||
this._language = settings.current
|
||||
this.defaultLanguage = settings.default
|
||||
this.supportedLanguages = settings.supportedLanguages
|
||||
globalThis.t = this.translate.bind(this)
|
||||
globalThis.i18n = this
|
||||
}
|
||||
merge(messages){
|
||||
this.messages = deepMerge(this.messages,messages)
|
||||
}
|
||||
|
||||
// 变量插值
|
||||
_replaceVars(source,params){
|
||||
if(Array.isArray(params)){
|
||||
return source.params(...params)
|
||||
}else{
|
||||
return source.params(params)
|
||||
throw new Error("Not supported language:"+value)
|
||||
}
|
||||
}
|
||||
/**
|
||||
*
|
||||
* translate("要翻译的文本内容") 如果默认语言是中文,则不会进行翻译直接返回
|
||||
* translate("I am {} {}","man") == I am man 位置插值
|
||||
* translate("I am {p}",{p:"man"}) 字典插值
|
||||
* translate("I am {p}",{p:"man",ns:""}) 指定名称空间
|
||||
* translate("I am {p}",{p:"man",namespace:""})
|
||||
* translate("I am {p}",{p:"man",namespace:""})
|
||||
* translate("total {count} items", {count:1}) //复数形式
|
||||
* translate({count:1,plurals:'count'}) // 复数形式
|
||||
* translate("total {} {} {} items",a,b,c) // 位置变量插值
|
||||
*
|
||||
*
|
||||
* 注册一个新的作用域
|
||||
*
|
||||
* 每一个库均对应一个作用域,每个作用域可以有多个语言包,且对应一个翻译函数
|
||||
* scope={
|
||||
* "<默认语言>":{
|
||||
* "<id>":"<text>",
|
||||
* },
|
||||
* "<语言1>":()=>import(),
|
||||
* "<语言2>":()=>import(),
|
||||
* }
|
||||
*
|
||||
* 除了默认语言外,其他语言采用动态加载的方式
|
||||
*
|
||||
* @param {*} scope
|
||||
*/
|
||||
translate(){
|
||||
let content = arguments[0],options={}
|
||||
try{
|
||||
if(arguments.length === 2 && typeof(arguments[1])=='object'){
|
||||
Object.assign(options,arguments[1])
|
||||
}else if(arguments.length >= 2){
|
||||
options=[...arguments].splice(1)
|
||||
}
|
||||
// 默认语言是中文,不需要查询加载,只需要做插值变换即可
|
||||
if(this.language === this.defaultLanguage){
|
||||
return this._replaceVars(content,options)
|
||||
}else{
|
||||
let result = this.messages[this.language][content]
|
||||
if(content in this.messages[this.language]){
|
||||
// 复数形式,需要通过plurals来指定内容中包括的复数插值
|
||||
if(Array.isArray(result)){
|
||||
let plurals = options.plurals
|
||||
if(typeof(plurals) == 'string' && (plurals in options)){
|
||||
return options[plurals]>1 ? result[1].params(options) : result[0].params(options)
|
||||
}else{
|
||||
return this._replaceVars(result[0],options)
|
||||
}
|
||||
}else{
|
||||
return this._replaceVars(result,options);
|
||||
}
|
||||
}else{
|
||||
return this._replaceVars(result,options)
|
||||
}
|
||||
}
|
||||
}catch(e){
|
||||
return content
|
||||
}
|
||||
register(scope){
|
||||
this._scopes.push(scope)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const i18nInstance = new i18n()
|
||||
|
||||
export default i18nInstance
|
||||
|
Loading…
x
Reference in New Issue
Block a user