为什么来自react-intl的defineMessages在传入对象引用时会抛出错误?

时间:2016-10-01 21:01:29

标签: reactjs webpack babeljs react-intl babel-plugin-react-intl

我正试图从雅虎的react-intl开始。 i18n项目,我遇到了一个奇怪的问题。我的目标是将基本字符串(英语)存储在组件外部的某种JSON文件中,以便非开发人员编辑它们。

这似乎比我import它们更合乎逻辑,然后在组件中使用我需要的部分,但是defineMessages函数在我这样做时会导致错误。

编辑:问题似乎是babel-plugin-react-intl插件和"导出"默认字符串。应用程序运行正常,但运行npm run build命令时会发生错误。

.babelrc:

{
    "presets": [
        "es2015",
        "react"
    ],
    "plugins": [
        ["react-intl", {
            "messagesDir": "./build/messages/"
        }]
    ]
}

的WebPack-配置:

module.exports = {
  entry: './src/app.js',   // The startingpoint of the app
  output: {
    filename: 'bundle.js',  // Name of the "compiled" JavaScript.
    path: './dist',         // Which dir to put it on disk.
    publicPath: '/',        // Which relative path to fetch code from on the client.
  },
  module: {
    loaders:[
      {
        test: /\.jsx?$/,            // Convert ES2015/React-code into ES5.
        exclude: /node_modules/,
        loader: 'babel'
      },
      {
        test: /\.json$/,            // Load JSON-files into code base.
        exclude: /node_modules/,
        loader: 'json',
      },
    ]
  },
};

的package.json:

{
  "name": "intl3",
  "version": "1.0.0",
  "description": "",
  "main": "webpack.config.js",
  "dependencies": {
    "babel-core": "^6.14.0",
    "babel-loader": "^6.2.5",
    "babel-plugin-react-intl": "^2.2.0",
    "babel-preset-es2015": "^6.14.0",
    "babel-preset-react": "^6.11.1",
    "eslint": "^3.3.1",
    "eslint-loader": "^1.5.0",
    "eslint-plugin-babel": "^3.3.0",
    "eslint-plugin-react": "^6.1.2",
    "json-loader": "^0.5.4",
    "react": "^15.3.2",
    "react-dom": "^15.3.2",
    "react-intl": "^2.1.5",
    "webpack": "^1.13.2",
    "webpack-dev-server": "^1.16.1"
  },
  "devDependencies": {
    "babel-plugin-react-intl": "^2.2.0",
    "babel-preset-react": "^6.16.0",
    "json-loader": "^0.5.4"
  },
  "scripts": {
    "start:dev": "webpack-dev-server --content-base ./ --config webpack.config.js",
    "prebuild": "cp index.html ./dist/index.html",
    "build": "webpack --config webpack.config.js",
    "start": "http-server dist"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

有效的代码:

import React from 'react';
import { FormattedMessage, defineMessages } from 'react-intl';

const strings = defineMessages({
    "title": {
        "id": "TITLE",
        "description": "Title of the app.",
        "defaultMessage": "Intl Company, Inc."
    },
    "menu": {
        "id": "MENU",
        "description": "Word for 'menu'.",
        "defaultMessage": "Menu"
    }
});

const Header = (props) => {
    return (
        <header>
            <div>
                <FormattedMessage {...strings.title} values={ { name: 'World' } } />
            </div>
        </header>
    );
};

export default Header;

失败的代码:

const headerStrings = {
    "title": {
        "id": "TITLE",
        "description": "Title of the app.",
        "defaultMessage": "Intl Company, Inc."
    },
    "menu": {
        "id": "MENU",
        "description": "Word for 'menu'.",
        "defaultMessage": "Menu"
    }
};

const strings = defineMessages(headerStrings);

尝试直接传递引用而不是对象时出现的错误消息:

./src/components/Header.js
Module build failed: SyntaxError: [React Intl] `defineMessages()` must be called with an object expression with values that are React Intl Message Descriptors, also defined as object expressions.

  17 | };
  18 | 
> 19 | const strings = defineMessages(headerStrings);
     |                 ^
  20 | 
  21 | const Header = (props) => {
  22 |     return (

BabelLoaderError: SyntaxError: [React Intl] `defineMessages()` must be called with an object expression with values that are React Intl Message Descriptors, also defined as object expressions.

  17 | };
  18 | 
> 19 | const strings = defineMessages(headerStrings);
     |                 ^
  20 | 
  21 | const Header = (props) => {
  22 |     return (

3 个答案:

答案 0 :(得分:1)

如果您将babel-plugin-react-intl与webpack一起使用,请确保仅通过.babelrcwebpack.config.js加载babel插件,但不能同时加载"target_link_libraries( # Specifies the target library. native-lib -ljnigraphics # Links the target library to the log library # included in the NDK. ${log-lib} ) [[UINavigationBar appearance] setBarTintColor:[UIColor colorWithRed:0.0 green:0.4705882353 blue:0.7450980392 alpha:1.0]]; 多次,在尝试通过webpack运行时会产生完全相同的错误。

答案 1 :(得分:1)

在搜索同一问题时发现了此问题,并认为我会留下对我帮助最大的答案(基于此问题的标题)。 defineMessages适用于babel-plugin-react-intl,我认为this issue可以更好地描述预期的功能,以及为什么不能传递先前定义的对象,以及为什么必须在致电defineMessages

引用Eric的回复:

  

由于Babel是编译器,而不是JavaScript解释器或运行时,因此您需要在defineMessages()调用站点定义要提取的消息。这意味着defineMessages()仅应在实际定义消息的地方使用,而不应在引用消息的地方使用。

     

此插件的全部目的是从源代码中提取消息,并且defineMessages()对此是一个钩子,并且期望消息描述符存在于调用站点中。 defineMessages()是一个识别函数,它返回传入的对象,因此最常见的用例是:

const messages = defineMessages({
    greeting: {
      id: 'home.greeting',
      defaultMessage: 'Hello, {name}!'
    }
});

<FormattedMessage {...messages.greeting}/>

答案 2 :(得分:0)

defineMessages的行为不是错误。此函数是一个钩子,用于“擦除”组件中的默认消息。如果您想要包含JSON import中的字符串,则defineMessages不是必需的,因为它的目的是导出您的默认消息以传递给翻译者。