从OneSky提取翻译文件并使用Gulp.js在AWS S3上发布

时间:2018-05-23 14:07:58

标签: amazon-s3 gulp

我正在编写一个Gulp脚本,以便将一些JSON文件推送到我的S3。 (我从OneSky下载翻译文件并将其推送到S3)。

我使用gulp-require-tasks软件包将我的任务拆分为子文件,因此我的任务文件如下:

const env = require('gulp-env')
const glob = require('glob')
const fs = require('fs')
const onesky = require('onesky-utils')
const path = require('path')
const AWS = require('aws-sdk/dist/aws-sdk-react-native')

TRANSLATION_LANGUAGES = ['fr-BE']

// ~~~~ Task ~~~~
module.exports = function() {
  env({ file: '.gulp-env.json' })

  for(var locale of TRANSLATION_LANGUAGES) {
    glob('./locales/' + process.env.ONESKY_BASE_LOCALE + '/*.json', {}, function (er, files) {
      files.forEach(function(file) {
        pullOneSkyFile(file, locale).then(content => {
          // Replace the root key with the current locale
          content = content.replace(process.env.ONESKY_BASE_LOCALE, locale)
          const translationFile = writeFile(file, locale, content)
          pushToAmazonS3(translationFile, locale, content)
        }).catch(error => {
          if (error.message === 'Invalid source file') {
            throw Error('The file', file, 'is not present on OneSky')
          } else {
            console.error('ERROR:', error)
          }
        })
      })
    })
  }
}

// ~~~~ Helper Methods ~~~~
function writeFile(file, locale, content) {
  const languageFolder = './locales/' + locale
  if (!fs.existsSync(languageFolder)) {
    console.log('Creating the folder', languageFolder)
    fs.mkdirSync(languageFolder);
  }

  const filePath = languageFolder + '/' + path.basename(file)
  fs.writeFileSync(filePath, content, 'utf-8');
  console.log('File', filePath, 'successfully updated localy for locale', locale, '.')
  return filePath
}

function pushToAmazonS3(filePath, locale, content) {
  console.log('Pushing the file', path.basename(filePath), 'with locale', locale, 'to Amazon S3...')

  const file = {
    // `uri` can also be a file system path (i.e. file://)
    uri: 'file://' + path.resolve(filePath),
    name: path.basename(filePath),
    type: 'application/json'
  }

  console.log('file', file)

  AWS.config.update({
    region: process.env.AMAZON_S3_REGION,
    accessKeyId: process.env.AMAZON_S3_ACCESS_KEY_ID,
    secretAccessKey: process.env.AMAZON_S3_SECRET_ACCESS_KEY
  })

  var s3 = new AWS.S3();
  s3.putObject({Bucket: 'companion-assets', Key: 'test', Body: content}, function (err) {
    if (err) {
      throw err
    } else {
      console.log('Uploading asset', file)
      fileStream.close()
    }
  })
}

function pullOneSkyFile(file, locale) {
  console.log('Pulling the file', path.basename(file), 'with locale', locale, '...')

  return onesky.getFile({
    apiKey: process.env.ONESKY_API_KEY,
    secret: process.env.ONESKY_SECRET_KEY,
    projectId: process.env.ONESKY_PROJECT_ID,
    language: locale,
    fileName: path.basename(file)
  })
}

当我执行此任务时,我有以下输出:

[15:55:07] Using gulpfile ~/Developments/companion/gulpfile.js
[15:55:07] Starting 'onesky-pull-aws-s3-push'...
locale fr-BE
Pulling the file screens.login.json with locale fr-BE ...
File ./locales/fr-BE/screens.login.json successfully updated localy for locale fr-BE .
Pushing the file screens.login.json with locale fr-BE to Amazon S3...
file { uri: 'file:///Users/zedtux/Developments/companion/locales/fr-BE/screens.login.json',
  name: 'screens.login.json',
  type: 'application/json' }
/Users/zedtux/Developments/companion/node_modules/aws-sdk/dist/aws-sdk-react-native.js:7090
                    throw err;
                    ^

NetworkingError: XMLHttpRequest is not defined
    at features.constructor.handleRequest (/Users/zedtux/Developments/companion/node_modules/aws-sdk/dist/aws-sdk-react-native.js:31583:16)
    at executeSend (/Users/zedtux/Developments/companion/node_modules/aws-sdk/dist/aws-sdk-react-native.js:6147:31)
    at Request.SEND (/Users/zedtux/Developments/companion/node_modules/aws-sdk/dist/aws-sdk-react-native.js:6161:11)
    at Request.callListeners (/Users/zedtux/Developments/companion/node_modules/aws-sdk/dist/aws-sdk-react-native.js:5704:20)
    at Request.emit (/Users/zedtux/Developments/companion/node_modules/aws-sdk/dist/aws-sdk-react-native.js:5680:12)
    at Request.emit (/Users/zedtux/Developments/companion/node_modules/aws-sdk/dist/aws-sdk-react-native.js:7742:16)
    at Request.transition (/Users/zedtux/Developments/companion/node_modules/aws-sdk/dist/aws-sdk-react-native.js:7081:12)
    at AcceptorStateMachine.runTo (/Users/zedtux/Developments/companion/node_modules/aws-sdk/dist/aws-sdk-react-native.js:7885:14)
    at /Users/zedtux/Developments/companion/node_modules/aws-sdk/dist/aws-sdk-react-native.js:7897:12
    at Request.<anonymous> (/Users/zedtux/Developments/companion/node_modules/aws-sdk/dist/aws-sdk-react-native.js:7097:11)
    at Request.<anonymous> (/Users/zedtux/Developments/companion/node_modules/aws-sdk/dist/aws-sdk-react-native.js:7744:14)
    at Request.callListeners (/Users/zedtux/Developments/companion/node_modules/aws-sdk/dist/aws-sdk-react-native.js:5718:20)
    at callNextListener (/Users/zedtux/Developments/companion/node_modules/aws-sdk/dist/aws-sdk-react-native.js:5698:14)
    at /Users/zedtux/Developments/companion/node_modules/aws-sdk/dist/aws-sdk-react-native.js:6063:11
    at finish (/Users/zedtux/Developments/companion/node_modules/aws-sdk/dist/aws-sdk-react-native.js:4746:9)
    at /Users/zedtux/Developments/companion/node_modules/aws-sdk/dist/aws-sdk-react-native.js:4764:11
    at Credentials.get (/Users/zedtux/Developments/companion/node_modules/aws-sdk/dist/aws-sdk-react-native.js:15525:8)
    at getAsyncCredentials (/Users/zedtux/Developments/companion/node_modules/aws-sdk/dist/aws-sdk-react-native.js:4758:26)
    at Config.getCredentials (/Users/zedtux/Developments/companion/node_modules/aws-sdk/dist/aws-sdk-react-native.js:4778:11)
    at Request.SIGN (/Users/zedtux/Developments/companion/node_modules/aws-sdk/dist/aws-sdk-react-native.js:6035:24)
    at Request.callListeners (/Users/zedtux/Developments/companion/node_modules/aws-sdk/dist/aws-sdk-react-native.js:5704:20)
    at Request.emit (/Users/zedtux/Developments/companion/node_modules/aws-sdk/dist/aws-sdk-react-native.js:5680:12)

我知道问题是AWS库是在Web浏览器或React本机应用程序中运行的,但在这种情况下我只是在编写一个glup脚本。

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

我实际上完全重写了所有内容,Glup方式,现在它工作得很好!

我不再使用gulpfile.js,这是我的代码。

const awspublish = require('gulp-awspublish') const env = require('gulp-env') const gulp = require('gulp') const oneSkyPull = require('./gulp-plugins/onesky-pull') const rename = require('gulp-rename') /* ** Pull translations from OneSky to the locale disk, then upload them to an * Amazon S3 bucket. */ gulp.task('i18n-deploy', function() { env({ file: '.gulp-env.json' }) // Load environment variables // Prepare the AWS S3 object var publisher = awspublish.create({ accessKeyId: process.env.AMAZON_S3_ACCESS_KEY_ID, secretAccessKey: process.env.AMAZON_S3_SECRET_ACCESS_KEY, region: process.env.AMAZON_S3_REGION, params: { Bucket: 'companion-assets' } }, { cacheFileName: 'aws-s3-cache' }) // Walk through all the base language translation files // The { base: 'companion' } here is used in order to keep the folder // strucutre on S3, otherwise the files were uploaded at the root of // the S3 bucket. gulp.src('./locales/' + process.env.ONESKY_BASE_LOCALE + '/*.json', { base: 'companion' }) .pipe(oneSkyPull({ baseLocale: process.env.ONESKY_BASE_LOCALE, locales: ['fr-BE'], // All translation languages oneskyApiKey: process.env.ONESKY_API_KEY, oneskySecretKey: process.env.ONESKY_SECRET_KEY, oneskyProjectId: process.env.ONESKY_PROJECT_ID })) // Fetch translation files from OneSky .pipe(rename(function(path) { // Remove the `../` part from the absolute path avoiding AWS error path.dirname = path.dirname.replace('../', '') })) .pipe(publisher.publish()) // Push to Amazon S3 })

const fs = require('fs')
const gutil = require('gulp-util')
const onesky = require('onesky-utils')
const path = require('path')
const through = require('through2')

const PLUGIN_NAME = 'onesky-pull'

// OneSky function to pull the translation file for the given locale
// and given file.
function oneSkyPullFile(file, locale, options) {
  console.log('Pulling the file', path.basename(file), 'with locale', locale, '...')

  return onesky.getFile({
    apiKey: options.oneskyApiKey,
    secret: options.oneskySecretKey,
    projectId: options.oneskyProjectId,
    language: locale,
    fileName: path.basename(file)
  })
}

// Write the translation files on the disk, creating the folders if needed.
// Returns a gutil.File to be pushed in the stream.
function writeFile(file, baseLocale, locale, content) {
  var languageFolder = path.dirname(file)
  languageFolder = languageFolder.replace(baseLocale, locale)
  if (!fs.existsSync(languageFolder)) {
    console.log('Creating the folder', languageFolder)
    fs.mkdirSync(languageFolder);
  }

  const filePath = languageFolder + '/' + path.basename(file)
  fs.writeFileSync(filePath, content, 'utf-8');
  console.log('File', filePath, 'successfully updated localy for locale', locale, '.')
  return new gutil.File({
    path: filePath,
    contents: new Buffer.from(content)
  })
}

// Plugin main functiomn
module.exports = function(options) {
  options = options || {}

  if (!options.baseLocale)
    throw new gutil.PluginError(PLUGIN_NAME, 'please specify the base locale (baseLocale)')

  if (!options.locales)
    throw new gutil.PluginError(PLUGIN_NAME, 'please specify the locales (locales)')

  if (!options.oneskyApiKey)
    throw new gutil.PluginError(PLUGIN_NAME, 'please specify your OneSky API Key (oneskyApiKey)')

  if (!options.oneskySecretKey)
    throw new gutil.PluginError(PLUGIN_NAME, 'please specify your OneSky Secret Key (oneskySecretKey)')

  if (!options.oneskyProjectId)
    throw new gutil.PluginError(PLUGIN_NAME, 'please specify your OneSky Project ID (oneskyProjectId)')

  return through.obj(function (file, encoding, callback) {
    if (file.isNull()) {
      this.push(file) // Do nothing if no contents
      return callback()
    }

    if (file.isBuffer()) {
      for(var locale of options.locales) {
        oneSkyPullFile(file.path, locale, options).then(content => {
          // OneSky build a JSON file based on the base language file with
          // the target locale translations.
          // So we replace the base locale with the current one.
          content = content.replace(options.baseLocale, locale)
          // Write the file on the disk
          const translationFile = writeFile(file.path, options.baseLocale, locale, content)
          // Add back the vynil file to the stream
          this.push(file)
          // Add the created translation file to the stream (so that it will be
          // available for the next plugins).
          this.push(translationFile)

          return callback()
        }).catch(error => {
          if (error.message === 'Invalid source file') {
            this.emit('error', new gutil.PluginError(PLUGIN_NAME, 'The file', file, 'is not present on OneSky'))
          } else {
            this.emit('error', new gutil.PluginError(PLUGIN_NAME, 'ERROR:' + error))
          }
          return callback()
        })
      }
    }

    if (file.isStream()) {
      this.emit('error', new gutil.PluginError(PLUGIN_NAME, 'ERROR: Streams are not supported'))
      return callback()
    }
  })
}

这是我的OneSky插件文件:

[12:15:45] Using gulpfile ~/Developments/companion/gulpfile.js
[12:15:45] Starting 'i18n-deploy'...
[12:15:45] Finished 'i18n-deploy' after 11 ms
Pulling the file screens.login.json with locale fr-BE ...
file /Users/zedtux/Developments/companion/locales/fr-FR/screens.login.json
path.dirname(file) /Users/zedtux/Developments/companion/locales/fr-FR
File /Users/zedtux/Developments/companion/locales/fr-BE/screens.login.json successfully updated localy for locale fr-BE .

运行任务会产生以下输出:

{{1}}