GithubHelp home page GithubHelp logo

react-i18nliner's Issues

coalesce wrappers without intermediate text nodes

This doesn't really affect functionality, but it does make for nicer translation strings... Consider:

<p translate="yes">Hello <b><i>{user}</i></b></p>

Currently that yields the translation string:

"Hello ** *%{user}* **"

The double wrappers add no value for translators, and are more likely to get screwed up. We should coalesce them so that the translators see:

"Hello *%{user}*"

i18nliner-handlebars and canvas_react_i18n both do this, we should too.

Even better would be no wrappers, if all that is contained is a placeholder, but we can save that for another ticket ๐Ÿ˜„

auto-translate translatable attributes in `translate="yes"` elements

Per the spec ... if a translatable attribute has literal text, and its element (or ancestor) has translate="yes", we should preprocess that into an I18n.t call. If the element (or ancestor) has translate="no", we should not. Non-translatable attributes should never be preprocessed into I18n.t calls.

Example:

<p translate="yes">
  Update your preferences <a href="/prefs" title="User Preferences">here</a>.
</p>

This would result in the strings "Update your preferences *here*" and "User Preferences" being extracted/translated, but of course "/prefs" would not.

Fails to compile for `{" "}`

Using {" "} is a very common way to add a white-space, however when used with react-i18nliner it causes a failure to compile.

preserve whitespace when preprocessing

to facilitate debugging, we should preserve whitespace (or at least newlines) when converting a translate="yes" component to a <ComponentInterpolator> ... that way line numbers will match up with the original source. as it stands right now, recast is injecting some newlines, presumably for readability.

we handle this kinda rudimentarily in i18nliner (erb)

webpack loader breaking on newer webpack versions

Hi John! ๐Ÿ‘‹

I ran into an error cannot read property 'noParse' of undefined after upgrading to webpack 3. It seems that this.options.module is now undefined ๐Ÿ˜ข . Looking over the docs on webpack loaders (https://webpack.js.org/contribute/writing-a-loader/) it seems they discourage accessing the options directly, and they even go so far as to say that options is read-only.

I was able to get things working by explicitly adding the noParse rule to my config:

noParse: /i18nliner\/dist\/lib\/i18nliner/,

and creating a simpler version of your webpack loader that doesn't set the noParse config anymore:

const I18nliner = require('i18nliner').default;
const hasTranslatableText = require('react-i18nliner/hasTranslatableText')(I18nliner.config);
const preprocess = require('react-i18nliner/preprocess');

module.exports = function i18nloader(source) {
  this.cacheable();

  if (hasTranslatableText(source)) {
    return preprocess(source, I18nliner.config);
  }
  return source;
};

I'm not sure if there's still a way to automatically set the noParse config from within the loader.

auto-translate elements

react-i18nliner lets you stick translate="yes" on anything, which is cool. But what would be really cool is if you could basically say "auto translate these tags/components unless they have a translate="no". In my mind, that's pretty much the holy grail of i18n ... you get to a point where you (almost) never have to do anything or even think about i18n; your app is just automagically localized.

For starters this could be an opt-in thing, by way of .i18nrc ... basically have a setting of the elements/components that should be auto-translated. Some sensible ones to turn on would be <p />, <th />, <label />, <h1 />, etc. You probably would not want to do it for <div /> or <span />

This is also nice because it makes for an easy upgrade path from canvas_react_i18n ... just create a <Text /> component that just renders its content, and set it to auto-translate.

It is a bit of a can of worms though, i.e. it dramatically increases the likelihood of nested translatable elements. In some cases you probably only want to translate the outer one (e.g. (<p>see the <a href="/">index</a></p>). We should probably make that happen automatically, if there are no intermediate non-translatable elements.

So that gets to a second point, you might need a list of auto-don't-translates ... Consider: <label>I live in <select placeholder="state"><option>Alabama<option>Alaska... ... it would be nice to set <label /> and <option /> to auto-translate, and <select /> to never translate. Then you'd get a string for the label text (plus placeholder), and a string for each state.

key collisions in ComponentInterpolator

given:

<div translate="yes">
  Your Score
  <b className="learnerScore">{score}</b><span className="superscript">%</span>
</div>

you get a placeholder for <b> and a wrapper for the <span>, and they both get key="1" ... keys should be unique across interpolated wrapper and placeholder components

dummy placeholders

right now react-i18nliner doesn't play nicely with i18nliner-js' JsProcessor or the i18n-js runtime, because it generates I18n.t calls with placeholders that have no corresponding values. strictly speaking there are values, but not in the I18n.t arguments, they are props of the <I18n.ComponentInterpolator>

a quick fix that would obviate the need for changing i18nliner-js or i18n-js would be to simply have dummy placeholder values that put the placeholder right back, e.g. user="%{user}". long term though it'd be great if i18nliner-js/i18n-js supported it (e.g. translateWithoutInterpolation, or change lookup to support a string-instead-of-key and make it extractable)

ComponentInterpolator should accept null/undefined/etc placeholder props

if a placeholder value is missing, you get <ComponentInterpolator> expected '${token}' placeholder value, none found ... right now it just does a falsy check, which is way too broad. instead we should see if it's present in props. if it is present, we should not raise an error, even if the value is undefined/null/false/0/""

Running tests fails on Windows

c:\ws\react-i18nliner> npm test

> [email protected] test c:\ws\react-i18nliner
> eslint . && node_modules/.bin/jest

'node_modules' is not recognized as an internal or external command,
operable program or batch file.
npm ERR! Test failed.  See above for more details.

I'll prepare a PR to fix this.

extra whitespace around placeholders/wrappers

given:

<div translate="yes">
  Your Score
  <b className="learnerScore">{score}</b><span className="superscript">%</span>
</div>

the pre-processed representation is:

<div>
  <I18n.ComponentInterpolator
    string={I18n.t("Your Score %{score} *%*", { "score": "%{score}" })}
    wrappers={{ "*": <span className="superscript">$1</span> }}
    score={<b className="learnerScore">{score}</b>}
  >$1</I18n.ComponentInterpolator>
</div>

note the whitespace between the score and the % ... we shouldn't introduce any whitespace not in the source. for adjacent placeholders this isn't a big deal, but it could be an issue for parsing wrappers (especially when dealing with nesting/etc.) ... might need to use different delimiters :'(

react-tools deprecated

Hi, doing npm install for the project I'm getting this warning:

(master) % cd react-i18nliner                                                                                                              ~/towbook
(master) % npm install                                                                                            ~/towbook/react-i18nliner
npm WARN package.json [email protected] No repository field.
npm WARN engine [email protected]: wanted: {"node":"0.8.x || 0.10.x"} (current: {"node":"0.12.4","npm":"2.10.1"})
npm WARN deprecated [email protected]: react-tools is deprecated. For more information, visit https://fb.me/react-tools-deprecated
npm WARN prefer global [email protected] should be installed with -g

merge wrappers into contained placeholder

Spawned from #3

If all that a wrapper contains is a placeholder (no text content), we should not create a wrapper and should instead merge its component(s) into the placeholder value, e.g. consider:

<p translate="yes">Hello <b>{user}</b></p>

Ideally that should yield the following (note the lack of wrapper):

"Hello %{user}"

The value for %{user} would be <b>{user}</b>

React.createClass is deprecated

I'm getting this warning when I run my tests:

Warning: Accessing createClass via the main React package is deprecated, and will be removed in React v16.0. Use a plain JavaScript class instead. If you're not yet ready to migrate, create-react-class v15.* is available on npm as a temporary, drop-in replacement. For more info see https://fb.me/react-create-class

It's being used in the definition of ComponentInterpolator. It looks from a cursory investigation like ComponentInterpolator could become a pure functional component if we were to pass keyCounter along when we recursively call interpolateAllComponents.

merge leading/trailing standalone elements into wrappers

Another thing for nicer translation strings... Consider:

<button onClick={this.close}>
  <Icon className="i-close" />
  <span translate="yes">Close</span>
</button>

The span is superfluous, but if we put translate="yes" on the <button /> then translators will see a placeholder for the <Icon />, which is not helpful.

If a wrapper has leading or trailing elements with no text content, we should absorb them into the wrapper. Then you can safely do:

<button onClick={this.close} translate="yes">
  <Icon className="i-close" />
  Close
</button>

an the extracted string will just be:

"Close"

i18nliner-handlebars and canvas_react_i18n both do this, we should too.

better inferred placeholder keys

right now it does a couple things when inferring a placeholder key from an expression:

  • snake case
  • remove invalid chars
  • remove this., this.props., and this.state. prefixes
  • remove closing tags

in addition it would be great to also:

  • remove all jsx so we are only inferring from vanilla javascript
  • remove this., this.props., and this.state. anywhere, not just in prefixes

speed up webpack and browserify

the webpack loader and browserify transform will do a full preprocess of every file they are given ... that means an esprima/acorn parse, a recast visit, and a recast print. we should skip files if we know we don't need to process them

we already have logic that does this for i18nliner:check ... a simple regex check for translatable content (based on .i18nrc settings)

some files mangled during preprocessing

this may be a recast printing bug, or it may be due to #1, or both ... i've got a file w/ some jsx like so

      <div>
        <LayoutItemHeader type="survey">
          ...
          <Block name="layout--item-header__actions">
            <SurveyHeaderActions
              survey={this.props.survey}
              permissions={this.props.permissions}
              media={this.state.media}
              handleClickPreview={this.handleClickPreview}
              handleDuplicate={this.handleDuplicate} />
          </Block>
        </LayoutItemHeader>

        <div className="survey-distributions large-content-area centered padding-trl-m-desktop padding-none-mobile">
          <div key="subtitle" className="clearfix padding-tb-l padding-xs-mobile grey-bg-mobile">
            <h2 className="margin-b-s left">
              {I18n.t("Distributions")}
            </h2>
            <DistributeBox groupSearch={this.props.groupSearch} surveyId={this.props.survey.id}>
              <button type="button" className="add-btn">
                <Text>+ <span className="add-btn__text">Distribute</span></Text>
              </button>
            </DistributeBox>
          </div>

          <DistributionList {...distributionProps} />
        </div>
      </div>

it gets preprocessed into this:

      <div>
        <LayoutItemHeader type="survey">
          ...
          <Block name="layout--item-header__actions">
            <SurveyHeaderActions
              survey={this.props.survey}
              permissions={this.props.permissions}
              me dia={t<I18n.ComponentInterpolator
                  string={I18n.t("+ *Distribute*")}
                  wrappers={{
                    "*": s.state.media}$1
                  }}>$1</I18n.ComponentInterpolator>
              handleClickPreview={this.handleClickPreview}
              handleDuplicate={this.handleDuplicate} />
          </Block>
        </LayoutItemHeader>

        <div className="survey-distributions large-content-area centered padding-trl-m-desktop padding-none-mobile">
          <div key="subtitle" className="clearfix padding-tb-l padding-xs-mobile grey-bg-mobile">
            <h2 className="margin-b-s left">
              {I18n.t("Distributions")}
            </h2>
            <DistributeBox groupSearch={this.props.groupSearch} surveyId={this.props.survey.id}>
              <button type="button" className="add-btn">
                <Text>+ <span className="add-btn__text">Distribute</span></Text>
              </button>
            </DistributeBox>
          </div>

          <DistributionList {...distributionProps} />
        </div>
      </div>

<Text> is an autoTranslateTag, and it does get preprocessed ... sort of, but in the wrong place. note the mangled media attribute inside <SurveyHeaderActions> ... totally broken

Sample Setup

Hello, I'm trying to follow the readme but I can't seem to make it work, is there any project sample(folder) that can be followed?

piggy-back on key for placeholder name

This could provide a mechanism to specify a friendlier placeholder, rather than letting it be inferred. For example:

<p translate="yes">
  Create <input onChange={this.createAccounts} /> new user accounts
</p>

Currently this yields "Create %{input_on_change_this_create_accounts} new accounts", which is terrible, and likely to change.

If we used the key, you could do this:

<p translate="yes">
  Create <input key="numAccounts" onChange={this.createAccounts} /> new user accounts
</p>

then the string could just be "Create %{num_accounts} new accounts"

ES6 support

Hi,
Seems react-i18nliner is not supporting ES6 classes?

ERROR in ./src/client.js
Module parse failed: /Users/erik/project1/node_modules/babel-
loader/index.js!/Users/erik/project1/node_modules/react-i18nliner/webpack-
loader.js!/Users/erik/project1/src/client.js Line 5: Unexpected reserved word
You may need an appropriate loader to handle this file type.

| import React from 'react';

Force a Language

Anyway to force a language for localization?
I assume by default, browser language is picked up.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.