code-i18n
What is this?
code-i18n
ๅผ็ฎฑๅณ็จ็้กน็ฎๅฝ้
ๅๅทฅๅ
ทใ
่ฎฟ้ฎhttps://vite-i18n.netlify.app/ๅฏไปฅๅจ้กน็ฎไธญๅฟซ้ไฝฟ็จ code-i18n
ใ
Type
็ฎๅๆฏๆ่ฝฌๆข็่ฏญ่จ
Type | Support |
---|---|
js | |
jsx | |
ts | |
tsx | |
vue |
Usage
code-i18n
ๅฏผๅบไธไธชๅพ็ฎๅ็ๅฝๆฐ๏ผๅๆฐๆฏ source
ๅ config
๏ผ่ฟๅๅผๆฏไธไธชๅฏน่ฑก๏ผ่ฏฆ่ง ๆๆกฃใ
import { transformCode } from 'code-i18n'
const source = 'const language = "ไธญๆ"'
const { code } = transformCode(source, {
type: 'js',
})
console.log(code) // const language = $t('StringLiteral_17_21');
console.log(stack) // [ { StringLiteral_17_21: "ไธญๆ" } ]
ๅฆๆๅ็่งฃๆ้่ฏฏ๏ผๆ่ฎธๆฏๅ ไธบไฝฟ็จไบ้ๅธธ่ง่ฏญๆณ๏ผๆฏๅฆ ๅฑๅผ่ฏญๆณ [Spread syntax]
๏ผ้ป่ฎคๆฏๆ๏ผใไฟฎ้ฅฐๅจ [Decorator]
๏ผไธ็จๆ
ๅฟ๏ผไฝ ๅฏไปฅๆ็
งๅฆไธ้
็ฝฎๅฏนไปฃ็ ่ฟ่ก้้
ใๅ
ถๅฎ่ฏญๆณ้่ฏฏๅฏไปฅๅ
ณๆณจ babel๏ผ่ฟ่กๅฏนๅบ็้
็ฝฎใ
transformCode(source, {
type: 'js',
parserOptions: {
babel: {
plugins: [['decorators', { decoratorsBeforeExport: true }]],
},
},
})
Installation
yarn add -D code-i18n
npm install --save-dev code-i18n
CLI
code-i18n
ๆไพไบ็ฎๅ้ซๆ็ๅฝไปค่ก๏ผ่พๅ
ฅ code-i18n --help
ๆฅ็ๆๆๆฏๆ็ๆไฝใไนๆไปฅๆฒก็จ code
ไฝไธบๅค้ๅ
ณ้ฎ่ฏ๏ผๆฏๅ ไธบ vscode ๆไพไบ code
ๅฝไปค่กใ
ๅฝไปค่ก้ป่ฎคไผ่ฏปๅๆง่ก่ทฏๅพไธ็ .code-i18n.js
ๆไปถใๅฆๆๅจๅฝไปค่กไธญๆๅฎไบ type
๏ผ้ฃไนไผ่ฆ็้
็ฝฎๆไปถไธญ็ type
ใ
่ฏฆ็ป้ ็ฝฎๅฆไธ๏ผ
const recast = require('recast')
const option = {
// ๅ่ https://github.com/Linkontoask/code-i18n/blob/next/types/interface/index.d.ts#L11
}
module.exports = {
...options,
ignore: [],
prettier: (code, ast) => {
if (ast) {
return recast.print(ast, {
tabWidth: 2
}).code
}
return code
}
}
ๅจ่ฟ่กไธๅๆไฝไนๅ๏ผ้่ฆๅ จๅฑๅฎ่ฃ
yarn global add code-i18n
npm install -g code-i18n
Usage: code-i18n [options]
Convert your code to help you code quickly (internationalization)
Options:
-v, --version output the version number
--debug Output more information for debugging the program (default: false)
--config <path> Specify the configuration file
-c, --code <code> Convert the specified code
-n, --name <file name> Convert the specified file
-d, --dir <directory> Convert files under the specified path
-s, --stack <file name> Specify the output location of the collected language pack (json)
-w, --write [path] Specify the write path (only used in --code and --name) or overwrite the current
file (default: false)
-t, --type <js | jsx | ts | tsx | vue> Specify the current code type, must be specified when using --code
-h, --help display help for command
ๆ็ๆถๅ๏ผๆๅชๆณ็็ไธไธช็ฎๅ็ไปฃ็ ่ฝฌๆข๏ผๆไปฌๅช้่ฆ่พๅ ฅๅฆไธไฟกๆฏ
code-i18n -c "const message = 'ๆ็ฑไธญๅฝ'" -t js
#โโโโโโโโโโโฌโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
#โ (index) โ name โ code โ stack โ
#โโโโโโโโโโโผโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
#โ 0 โ null โ "const message = $t ...... teral_1_16_1_22');" โ '{"StringLiteral_1_16_1_22":"ๆ็ฑไธญๅฝ"}' โ
#โโโโโโโโโโโดโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ๅ
ถไธญ็ไฟกๆฏ่ขซ่ฃๅชไบ๏ผๅ ไธบๅจ console
ๅฑๅนไธๆฒกๅๆณๅฑ็คบๆๆไฟกๆฏ๏ผ่ฟไธชๆถๅๅฏไปฅๆทปๅ --write
ๅๆฐ๏ผๅฐไปฃ็ ่พๅบๅฐๆไปถไธญ
code-i18n -c "const message = 'ๆ็ฑไธญๅฝ'" -t js --write china.js
// china.js
const message = $t('StringLiteral_1_16_1_22');
code-i18n
่ฟๅฏไปฅ่ฝฌๆขๅฏนๅบ็ๆไปถ๏ผๅนถไธๆๅ
ถ็ฎๅ
code-i18n -n china.js -w
่ฝฌๆข็ฎๅฝไธๆๆ js
ๆไปถ๏ผๅนถไธๅๅ
ฅ
code-i18n -d . -t js -w
ๅฐ่ฟ้๏ผไฝ ไผๅ็ฐ๏ผ่ฟๆฒกๆ็ๆ่ฏญ่จๅ
ใๆไปฌๅจๅฝไปค่กไธญๆทปๅ -s <path>
ๅฐฑๅฏไปฅไบ๏ผไปไผๆไปฃ็ ไธญๆๆไธญๆไฟกๆฏ่พๅบๅฐไธไธช json ๆไปถไธญใ
code-i18n -d . -t js -s zh-cn.json -w
Documentation
ไธ้ขไฝฟ็จ typescript ็ๅฝขๅผไป็ป code-i18n
ไฝฟ็จๆนๆณใๅ
ถไธญๆไบๆๆกฃ้่ฆๅ่่ฟไบๅฐๆน vue-eslint-parserใbabel-parserใespree
import { ParserOptions as BabelParserOptions } from '@babel/parser'
import { Linter } from 'eslint'
interface ParserOptions {
vue?: Linter.ParserOptions
babel?: BabelParserOptions
}
interface Config {
type: 'js' | 'jsx' | 'ts' | 'tsx' | 'vue'
identifier?: string
ruleKey?: (node: t.Node) => string | number
parserOptions?: ParserOptions
}
export declare function transformCode(
code: string,
config: Config
): {
code: string
stack: Record<string, string>[]
}
็ฐๅจ๏ผparserOptions
ๅทฒ็ปๅญๅจ้ป่ฎคๅผ๏ผๅฝไฝ ๅ็ๆไปปไฝ่ฏญๆณ้่ฏฏ็ๆถๅๆฃๆฅๆญค้ป่ฎคๅผๆฏๅฆ็ฌฆๅ้ขๆใๆฏๅฆๅฝไฝ ๅ็ฐๆ optional expression
๏ผๅฏ้้พ๏ผ ้่ฏฏ็ๆถๅ๏ผไฝ ้่ฆ้
็ฝฎๅฆไธไฟกๆฏใ้ๅธธๅจ่งฃๆ vue
ๆไปถ็ๆถๅๆไผๅบ็ฐ่ฟไบ้ฎ้ขใ
transformCode(source, {
parserOptions: {
vue: {
ecmaVersion: 11,
},
},
})
ๆ็ๆถๅๆไปฌๅจ็ผๅ vue
ไปฃ็ ็ๆถๅ้่ฆไฝฟ็จ jsx
็่ฏญๆณ๏ผ็ฐๅจไฝ ๅฟ
้กปๅฐ parserOptions
็ vue ๅฑๆง่ฟ่กๆดๆนใ
transformCode(source, {
parserOptions: {
vue: {
ecmaFeatures: {
jsx: true,
},
},
},
})
ๆไปฌ่ฟๅฏไปฅๅ eslint
ไธๆ ท๏ผ่ฟๆปคๆไธไบไธ้่ฆ่ฝฌๆข็ๆไปถๆไปฃ็ ่กใ
// code-i18n-disabled
const country = 'ไธญๅฝ'
const city = '้ๅบ'
// ไธ้ขๆๆไธญๆ้ฝไธไผ่ฝฌๆข
const country = 'ไธญๅฝ'
// code-i18n-disabled-next-line
const city = '้ๅบ' // ่ฟ่กไปฃ็ ไธไผ่ฝฌๆข
ๅฅฝไบ๏ผ่ฏดไบ่ฟไนๅค๏ผไธ้ขๅฐฑๆฏ parserOptions
็้ป่ฎคๅผใ
const DEFAULT_PARSER_OPTIONS = {
// https://github.com/eslint/espree#options
vue: {
sourceType: 'module',
ecmaVersion: 11,
ecmaFeatures: {
experimentalObjectRestSpread: true,
},
},
babel: {
sourceType: 'module',
},
}
Example
่ฟ้ไฝฟ็จไธๆฎตไปฃ็ ๆฅไป็ป code-i18n
็้กน็ฎ็จๆณใ้ๅธธๅจๅไปฃ็ ็่ฟ็จไธญ๏ผ้่ฆๆถๅปๆณจๆๆๆฌ็็กฌ็ผ็ ๏ผๅ ไธบ่ฟไผ่ฎฉไบงๅๅคฑๅปไธๅ่ฏญ่จ็็จๆทใๅธๅบไธๆๅ็ฐไบไธไบๅผๆบ้กน็ฎ๏ผไปไปฌ้่ฟ webpack ็่ฝๅ๏ผๅจ build
ๆ้ด๏ผๅๆ็ปไบง็ฉๆทปๅ ไธๅฏ้็่ฝฌๆขไปฃ็ ๏ผ่ฟๅพไธๅๅฅฝ๏ผๅนถไธๅจๅ็้่ฏฏ็ๅๆถๅพ้พๅป็ๅซใ
code-i18n
ๆฏๅฐๆบ็ ไธญ็ๅญ็ฌฆไธฒๆฟๆขๆๅฏๆง่กๅฝๆฐ๏ผๅจๅผๅ็ๅๆถๅณๅฏ้
่ฏป่ฏญ่จ้จๅ็ๆบ็ ๏ผๅนถไธๅฏไปฅๅฐๅทฒ็ปๅๅธ็ไบงๅๅฝ้
ๅๅค็ใ่ฟ้ฝๅพ็ไบๆฅ่ถๅผบๅคง็ๅผๆบ็คพๅบ๏ผๅจ่ฟ้ๆ่ฐข babel
ๅ eslint
็ป็ปใ
ไธ้ขๆฏๅธฎๅฉๆไปฌๅฐ้กน็ฎไธญๆๆไธญๆๅญ็ฌฆ่ฝฌๆขๆ $t('xxxx')
็ๅฝๆฐ๏ผๅฆๆๅ็้่ฏฏๅฐๆๅฐๅฏนๅบ็ๆไปถ่ทฏๅพๅ้่ฏฏๆฅๅฟ
const glob = require('glob')
const path = require('path')
const fs = require('fs')
const { transformCode } = require('../../code-i18n/index')
const root = path.resolve(__dirname)
glob(
'test/**',
{
cwd: root,
},
(err, matches) => {
const paths = matches
.filter((matche) => ['js', 'jsx', 'ts', 'tsx', 'vue'].includes(path.extname(matche).slice(1)))
.map((item) => path.join(root, item))
const content = paths.map((p) => fs.readFileSync(p, 'utf-8'))
content
.map((item, index) => (/[\u4e00-\u9fa5]/.test(item) ? { content: item, path: paths[index] } : false))
.filter((a) => a)
.forEach((source) => {
try {
const filetype = path.extname(source.path).slice(1)
const { code } = transformCode(source.content, {
type: filetype,
parserOptions: {
vue: {
ecmaVersion: 11,
ecmaFeatures: {
jsx: true,
},
},
},
})
fs.writeFileSync(source.path, code, { encoding: 'utf-8' })
} catch (e) {
console.log(source.path, e)
}
})
}
)
Features
่ฟ้ๅฑ็คบ็ๆฏ AST
ไธญๅฏนๅบ็ Node๏ผๆดๅคไฟกๆฏๅ่ estreeใ
- StringLiteral
- TemplateLiteral
- JSXText
- JSXAttribute
- Vue
- Literal
- VText
- VAttribute
- VLiteral
- TemplateLiteral
Tests
่ฟ่ก yarn test
่ฟ่กๆต่ฏใ
ๅฝๅๆต่ฏ่ฆ็็่กจใ
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
---|---|---|---|---|---|
All files | 100 | 90.57 | 100 | 100 | |
core | 100 | 90.57 | 100 | 100 | |
parser.ts | 100 | 100 | 100 | 100 | |
transform.ts | 100 | 91.3 | 100 | 100 | 68,107 |
vue.ts | 100 | 89.29 | 100 | 100 | 38,147,170 |
utils | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 |