1

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

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

编辑:问题似乎与babel-plugin-react-intl插件和“导出”默认字符串有关。该应用程序运行良好,但当npm run build命令运行时发生错误。

.babelrc:

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

网络包配置:

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',
      },
    ]
  },
};

包.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 (
4

3 回答 3

2

在搜索相同问题时发现了这个,并认为我会留下对我帮助最大的答案(基于这个问题的标题)。defineMessages旨在用于babel-plugin-react-intl,我认为这个问题更好地描述了预期的功能以及为什么传入先前定义的对象不起作用以及为什么必须在调用中定义消息defineMessages

引用埃里克的回应:

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

这个插件的重点是从源代码中提取消息,并且 defineMessages() 是一个钩子,并且预计消息描述符存在于调用站点中。defineMessages() 是一个识别函数,返回传入的对象,所以最常见的用例是:

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

<FormattedMessage {...messages.greeting}/>
于 2019-01-18T19:39:17.737 回答
1

如果您babel-plugin-react-intl与 webpack 一起使用,请确保您只加载一次 babel 插件,通过.babelrcwebpack.config.js,但不能同时加载,因为它会导致插件被多次加载,在尝试运行时会导致完全相同的错误通过网页包。

于 2016-10-01T22:17:42.600 回答
1

的行为defineMessages不是错误。这个函数是一个从组件中“抓取”默认消息的钩子。如果您想包含来自 JSON 的字符串importdefineMessages则没有必要,因为它的目的是导出您的默认消息以传递给翻译器。

于 2016-10-04T16:55:51.913 回答