Git Product home page Git Product logo

ast-i18n's Introduction

AST i18n Build Status

The objective of this tool is to make easy to migrate an existing codebase to use i18n

How it works

  • it gets a list of files from the command line
  • it runs a babel plugin transform to find all string inside JSXText
  • it generates a stable key for the extracted strings
  • it generates i18n files format based on this map
  • it modify your existing code to use i18n library of your preference

Example

Before this transform

import React from 'react';

const Simple = () => (
  <span>My simple text</span>
);

After this transform

import React from 'react';
import { withTranslation } from 'react-i18next'

const Simple = ({ t }) => (
  <span>{t('my_simple_text')}</span>
);

Usage of string extractor

yarn start --src=myapp/src
  • It will generate a resource.jsx file, like the below:
export default {
  translation: {
   'ok': `ok`,
   'cancelar': `cancelar`,
   'continuar': `continuar`,
   'salvar': `salvar`,
   'endereco': `endereço:`,
   'troca_de_senha': `troca de senha`,
   'dados_pessoais': `dados pessoais`,
   [key]: 'value',
  }
}

How to use resource with react-i18next?

  • rename resource.tsx to your main language, like en.ts
  • create other resource languages based on the generated one
import en from './en';

i18n.use(LanguageDetector).init({
  resources: {
    en,
  },
  fallbackLng: 'ptBR',
  debug: false,

  interpolation: {
    escapeValue: false, // not needed for react!!
    formatSeparator: ',',
  },

  react: {
    wait: true,
  },
});

Usage of i18n codemod

npm i -g jscodeshift

jscodeshift -t src/i18nTransformerCodemod.ts PATH_TO_FILES

How to customize blacklist

Use ast.config.js to customize blacklist for jsx attribute name and call expression calle

module.exports = {
  blackListJsxAttributeName: [
    'type',
    'id',
    'name',
    'children',
    'labelKey',
    'valueKey',
    'labelValue',
    'className',
    'color',
    'key',
    'size',
    'charSet',
    'content',
  ],
  blackListCallExpressionCalle: [
    't',
    '_interopRequireDefault',
    'require',
    'routeTo',
    'format',
    'importScripts',
    'buildPath',
    'createLoadable',
    'import',
    'setFieldValue',
  ],
};

ast-i18n's People

Contributors

antoni avatar dependabot[bot] avatar eveningkid avatar guilhermedecampo avatar jgcmarins avatar katilius avatar renanmav avatar sibelius avatar wdoug avatar xerosanyam avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ast-i18n's Issues

bug with svg

I've ran the script on my code base and still got some translated svg.
I guess that in #44 was just added the i18n Transformer Codemod.

Translate conditional expressions

Expanded current test case ExpressionContainer:

import React from "react";

const Simple = ({ enabled }) => (
  <>
    <span>{"My simple text"}</span>
    <span>{enabled ? "OK" : "Not OK"}</span>
    <span>{enabled && enabled}</span>
  </>
);

export default Simple;

The first case works fine, but other 2 are not translated.

withTranslation codemod

import { withTranslation } from 'react-i18next';

export default withTranslation()(MyComponent);
  • add withTranslation import if the component using i18n but it has not imported yet
  • add withTranslation() hoc to component that uses t function
  • add prop t to component
  • handle both functions and classes

Example

before:

import React from 'react';

const Simple = () => (
  <span>My simple text</span>
);

after

import React from 'react';
import { withTranslation } from 'react-i18next';

const Simple = ({ t } ) => (
  <span>{t('my_simple_text')}</span>
);

export default withTranslation()(Simple);

handle function calls

handle functions like this:

showSnackbar({ message: 'User editted successfully!'});

Missing lib folder on published package

The problem

I have installed this package from npm with yarn add ast-i18n.

Tried to execute the cli with yarn ast-i18n --src=packages/web/src and end up with this:

yarn ast-i18n --src=packages/web/src
yarn run v1.19.1
$ /Users/renan/www/foton/confy/node_modules/.bin/ast-i18n --src=packages/web/src
internal/modules/cjs/loader.js:775
    throw err;
    ^

Error: Cannot find module '../lib/cli.js'
Require stack:
- /Users/renan/www/foton/confy/node_modules/ast-i18n/bin/cli
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:772:15)
    at Function.Module._load (internal/modules/cjs/loader.js:677:27)
    at Module.require (internal/modules/cjs/loader.js:830:19)
    at require (internal/modules/cjs/helpers.js:68:18)
    at Object.<anonymous> (/Users/renan/www/foton/confy/node_modules/ast-i18n/bin/cli:3:1)
    at Module._compile (internal/modules/cjs/loader.js:936:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:947:10)
    at Module.load (internal/modules/cjs/loader.js:790:32)
    at Function.Module._load (internal/modules/cjs/loader.js:703:12)
    at Function.Module.runMain (internal/modules/cjs/loader.js:999:10) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [ '/Users/renan/www/foton/confy/node_modules/ast-i18n/bin/cli' ]
}
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

The why's

The cli is as follows.

#!/usr/bin/env node
require('../lib/cli.js').run();

Checking the node_modules folder I see this:

image

There isn't such lib folder. We should generate it along with its type declarations and minified version.

improve README with samples

Improve README with some gifs showing how it works in practice.

Clone the project, then:

 ~/Developer/ast-i18n>  yarn start --src=/home/user/Developer/project_that_u_want_put_i18n/src

Improve --src flag

I would like to use the CLI like this:

ast-i18n ./packages/web/src/*.ts

instead of --src=/packages/web/src/*.ts.

The enhanced way would able terminal autocomplete.

handle Yup required

withFormik<Props, Values>({
    mapPropsToValues: () => ({}),
    validationSchema: Yup.object().shape({
      type: Yup.string().required('Title is required'),
    }),
    handleSubmit: () => {},
  })(MyForm),

is there a patter matching for tree structures?

I'd like a node like this Yup.**.required

handle params

Options (e.g. for pluralization, or adding context/screenshots for translators) are specified like this:

const thisManyApples = t('{user} ate {count} apples', {count: 3, user: '@sseraphini '})

Make t function call configurable

Tagged Template Literals allows you to call the function by providing just ticks. This could be leveraged, to make syntax a bit less verbose, when dealing with translations:

<span>{t('key')}</span>

becomes

<span>{t`key`}</span>

This is, of course, a matter of preference, so it probably should be configurable.

add tests

tests will make sure we don't break anything

Create npm module for converter

Currently, in order to use this module you need to:

  1. Check out this repo locally
  2. install jscodeshift globally or use npx to call jscodeshift globally.

This lib could be published as npm module in a way, that it is callable same as jscodeshift. So anyone who would want to use this, could execute some command like:

npx ast-i18n --config config.js --path my-project/src

useTranslation codemod

related to #22

import { useTranslation } from 'react-i18next';
  • add useTranslation import if the component using i18n but it has not imported yet
  • add useTranslation hook only on functional components
  • handle both functions and classes

Example

before:

import React from 'react';

const Simple = () => (
  <span>My simple text</span>
);

after

import React from 'react';
import { useTranslation } from 'react-i18next';

const Simple = () => {
   const { t } = useTranslation();

  return (
      <span>{t('my_simple_text')}</span>
   );
}

export default Simple;

transform validationSchema of formik

from this:

validationSchema: Yup.object().shape({
      name: Yup.string().required('Name is required),
      email: Yup.string().email('Invalid email'),
    }),

to:

validationSchema: ({ t }) => Yup.object().shape({
      name: Yup.string().required(t('name_is_required')),
      email: Yup.string().email(t('invalid_email')),
    }),
  • validationSchema should be a callExpression instead of an object

improve tests

const { defineTest } = require("jscodeshift/dist/testUtils");

use defineTest helper of jscodeshift to run tests

Improve stableString

Referring to this line comment, https://github.com/sibelius/ast-i18n/blob/master/src/__test__/stableString.test.ts#L27

Maybe it would be simpler to use a package that gets a slug from a string instead, so that it covers all weird use cases already. What do you think @sibelius?

https://www.npmjs.com/package/slugify
Try it at https://npm.runkit.com/slugify

Note: turned out that when trying with the following:

slugify('éé-×', '_') // returns "ee-"

Then maybe just inspire your code from their code instead.

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.