Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
{
"extends": ["precure/oss"],
"extends": ["precure/auto"],
"rules": {
"@typescript-eslint/explicit-function-return-type": "off"
}
}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
node_modules
lib
example/i18n
dist
.eslintcache
6 changes: 1 addition & 5 deletions cli.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env node
/* eslint-disable no-console */
/* eslint-disable no-console, @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */
'use strict'
const meow = require('meow')
const fn = require('.')
Expand All @@ -16,7 +16,6 @@ const cli = meow(
-f, --format json | yaml [default: json]
-d, --default-locale default locale
--flat json [default: true] | yaml [default: false]
--module-name module source name from where components are imported

Example
$ extract-messages --locales=ja,en --output app/translations 'app/**/*.js'
Expand Down Expand Up @@ -44,9 +43,6 @@ const cli = meow(
type: 'string',
alias: 'd'
},
'module-name': {
type: 'string'
},
withDescriptions: {
type: 'boolean',
default: false
Expand Down
125 changes: 3 additions & 122 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,123 +1,4 @@
/* eslint-disable no-unused-vars */
'use strict'
const path = require('path')
const fs = require('fs')
const mkdirp = require('mkdirp')
const pick = require('lodash.pick')
const yaml = require('js-yaml')
const pify = require('pify')
const { flatten, unflatten } = require('flat')
const loadJsonFile = require('load-json-file')
const writeJsonFile = require('write-json-file')
const sortKeys = require('sort-keys')
const extractReactIntl = require('./extract-react-intl')
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
const fn = require('./dist').default

const writeJson = (outputPath, obj) => {
return writeJsonFile(`${outputPath}.json`, obj, { indent: 2 })
}

const writeYaml = (outputPath, obj) => {
return pify(fs.writeFile)(`${outputPath}.yml`, yaml.safeDump(obj), 'utf8')
}

const isJson = ext => ext === 'json'

function loadLocaleFiles(locales, buildDir, ext) {
const oldLocaleMaps = {}

try {
mkdirp.sync(buildDir)
} catch (error) {}

for (const locale of locales) {
const file = path.resolve(buildDir, `${locale}.${ext}`)
// Initialize json file
try {
const output = isJson(ext) ? JSON.stringify({}) : yaml.safeDump({})
fs.writeFileSync(file, output, { flag: 'wx' })
} catch (error) {
if (error.code !== 'EEXIST') {
throw error
}
}

let messages = isJson(ext)
? loadJsonFile.sync(file)
: yaml.safeLoad(fs.readFileSync(file, 'utf8'), { json: true })

messages = flatten(messages)

oldLocaleMaps[locale] = {}
for (const messageKey of Object.keys(messages)) {
const message = messages[messageKey]
if (message && typeof message === 'string' && message !== '') {
oldLocaleMaps[locale][messageKey] = messages[messageKey]
}
}
}

return oldLocaleMaps
}

// eslint-disable-next-line max-lines-per-function
module.exports = async (locales, pattern, buildDir, opts) => {
if (!Array.isArray(locales)) {
throw new TypeError(`Expected a Array, got ${typeof locales}`)
}

if (typeof pattern !== 'string') {
throw new TypeError(`Expected a string, got ${typeof pattern}`)
}

if (typeof buildDir !== 'string') {
throw new TypeError(`Expected a string, got ${typeof buildDir}`)
}

const jsonOpts = { format: 'json', flat: true }
const yamlOpts = { format: 'yaml', flat: false }
const defautlOpts =
opts && opts.format && !isJson(opts.format) ? yamlOpts : jsonOpts

opts = { defaultLocale: 'en', ...defautlOpts, ...opts }

const ext = isJson(opts.format) ? 'json' : 'yml'

const { defaultLocale, moduleName } = opts

const oldLocaleMaps = loadLocaleFiles(locales, buildDir, ext)

delete opts.defaultLocale

const extractorOptions = { defaultLocale, ...opts }

if (moduleName) {
extractorOptions.moduleSourceName = moduleName
}

const newLocaleMaps = await extractReactIntl(
locales,
pattern,
extractorOptions
)

return Promise.all(
locales.map(locale => {
// If the default locale, overwrite the origin file
let localeMap =
locale === defaultLocale
? // Create a clone so we can use only current valid messages below
{ ...oldLocaleMaps[locale], ...newLocaleMaps[locale] }
: { ...newLocaleMaps[locale], ...oldLocaleMaps[locale] }
// Only keep existing keys
localeMap = pick(localeMap, Object.keys(newLocaleMaps[locale]))

const fomattedLocaleMap = opts.flat
? sortKeys(localeMap, { deep: true })
: unflatten(sortKeys(localeMap), { object: true })

const fn = isJson(opts.format) ? writeJson : writeYaml

return fn(path.resolve(buildDir, locale), fomattedLocaleMap)
})
)
}
module.exports = fn
12 changes: 12 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module.exports = {
testPathIgnorePatterns: [
'<rootDir>[/\\\\](dist|compiled|node_modules)[/\\\\]'
],
testEnvironment: 'node',
preset: 'ts-jest',
globals: {
'ts-jest': {
diagnostics: false
}
}
}
22 changes: 18 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@
"add-contributor": "all-contributors add",
"fmt": "prettier --write '**/*.{json,js,md}'",
"example": "./cli.js -l=en,ja -o example/i18n -d en 'example/**/*.js'",
"lint": "eslint index.js cli.js ./extract-react-intl/index.js",
"build": "tsc",
"lint": "eslint src/**/*.ts --fix --cache",
"test": "npm run lint && jest"
},
"bin": {
"extract-react-intl-messages": "cli.js",
"extract-messages": "cli.js"
},
"files": [
"extract-react-intl/index.js",
"dist",
"index.js",
"cli.js"
],
Expand Down Expand Up @@ -56,10 +57,21 @@
"write-json-file": "^4.1.1"
},
"devDependencies": {
"@akameco/tsconfig": "^0.3.0",
"@babel/plugin-proposal-class-properties": "^7.5.5",
"@babel/preset-env": "^7.5.5",
"@babel/preset-flow": "^7.0.0",
"@babel/preset-react": "^7.0.0",
"@types/flat": "^0.0.28",
"@types/jest": "^24.0.18",
"@types/js-yaml": "^3.12.1",
"@types/lodash.merge": "^4.6.6",
"@types/lodash.mergewith": "^4.6.6",
"@types/lodash.pick": "^4.4.6",
"@types/mkdirp": "^0.5.2",
"@types/pify": "^3.0.2",
"@types/temp-write": "^4.0.0",
"@types/tempy": "^0.3.0",
"all-contributors-cli": "^6.8.1",
"babel-core": "7.0.0-bridge.0",
"babel-jest": "^24.8.0",
Expand All @@ -71,9 +83,11 @@
"lint-staged": "^9.2.1",
"prettier": "^1.18.2",
"react": "^16.8.6",
"react-intl": "^3.1.10",
"react-intl": "^3.1.11",
"temp-write": "^4.0.0",
"tempy": "^0.3.0"
"tempy": "^0.3.0",
"ts-jest": "^24.0.2",
"typescript": "^3.5.3"
},
"lint-staged": {
"*.{js}": [
Expand Down
8 changes: 0 additions & 8 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ $ extract-messages --help
-f, --format json|yaml [default: json]
--flat json [default: true] | yaml [default: false]
--default-locale default locale [default: en]
--module-name module source name from where components are imported [default: react-intl]

Example
$ extract-messages --locales=ja,en --output app/translations 'app/**/*.js'
Expand Down Expand Up @@ -171,13 +170,6 @@ If format is `yaml`, set to `false`.
Be careful if `false`.
See [this issue](https://github.com/akameco/extract-react-intl-messages/issues/3).

##### moduleName

Type: `string`<br>
Default: `react-intl`

Set from where _defineMessages_, `<FormatterMessage />` and `<FormattedHTML />` are imported.

##### babel-plugin-react-intl's Options

See https://github.com/formatjs/formatjs/tree/master/packages/babel-plugin-react-intl#options
Expand Down
6 changes: 6 additions & 0 deletions src/babel__core.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import babel from '@babel/core'

declare module '@babel/core' {
function resolvePlugin(name: string, dirname: string): string | null
function resolvePreset(name: string, dirname: string): string | null
}
Loading