i18next-scanner
i18next-scanner copied to clipboard
Extraction from tsx file
Can I extract language from a tsx file (react component) as shown below? If yes, what config file do I need to make this happen?
import React, { useState } from "react";
import { useForm, FormContext, ErrorMessage } from "react-hook-form";
import axios from "axios";
// See https://github.com/i18next/react-i18next/blob/master/test/typescript/examples.test.tsx
import {
useTranslation,
Trans,
withTranslation,
WithTranslation
} from "react-i18next";
import * as Yup from "yup";
import {
Button,
FormGroup,
FormControl,
FormLabel,
Form,
Modal,
Navbar,
Nav
} from "react-bootstrap";
import PropTypes, { InferProps } from "prop-types";
const styles = require("./Register.scss");
type FormData = {
username: string;
email: string;
password: string;
repeatpassword: string;
};
Register.propTypes = {
open: PropTypes.bool.isRequired,
closeAction: PropTypes.func.isRequired
};
export default function Register({
open,
closeAction
}: InferProps<typeof Register.propTypes>) {
const { t, i18n } = useTranslation();
const methods = useForm<FormData>({
validationSchema: Yup.object().shape({
username: Yup.string().required(t("Insert name")),
email: Yup.string()
.email(t("Invalid email"))
.required(t("Insert email")),
password: Yup.string()
.required(t("Password is required"))
.min(8, t("Password is too short - should be 8 chars minimum."))
.matches(/[a-zA-Z]/, t("Password can only contain Latin letters.")),
repeatpassword: Yup.string().oneOf(
[Yup.ref("password"), null],
t("Passwords must match")
)
})
});
const { register, handleSubmit, watch, errors } = methods;
const onSubmit = handleSubmit(
({ username, email, password, repeatpassword }) => {
console.log({ username, email, password, repeatpassword });
}
);
return (
<>
<Modal size="sm" show={open} onHide={closeAction}>
<Modal.Header closeButton>
<Modal.Title id="signup-title">{t("Sign up")}</Modal.Title>
</Modal.Header>
<Modal.Body id="signup-modal-body">
<Navbar bg="light" expand="lg">
<Navbar.Brand href="/">{t("Already a member?")}</Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="mr-auto"></Nav>
<Form inline>
<Nav.Link className="text-weight-bold" href="#">
{t("Login")}
</Nav.Link>
</Form>
</Navbar.Collapse>
</Navbar>
<FormContext {...methods}>
<Form onSubmit={handleSubmit(data => console.log(data))} noValidate>
<FormGroup controlId="username">
<FormLabel>{t("Username")}</FormLabel>
<FormControl
name="username"
type="text"
ref={register}
isInvalid={!!errors.username}
></FormControl>
<ErrorMessage
type="invalid"
name="username"
errors={errors}
as={Form.Control.Feedback}
/>
</FormGroup>
<FormGroup controlId="email">
<FormLabel>{t("E-mail")}</FormLabel>
<FormControl
name="email"
type="email"
ref={register}
isInvalid={!!errors.email}
></FormControl>
<ErrorMessage
type="invalid"
name="email"
errors={errors}
as={Form.Control.Feedback}
/>
</FormGroup>
<FormGroup controlId="password">
<FormLabel>{t("Password")}</FormLabel>
<FormControl
name="password"
type="password"
ref={register}
isInvalid={!!errors.password}
></FormControl>
<ErrorMessage
type="invalid"
name="password"
errors={errors}
as={Form.Control.Feedback}
/>
</FormGroup>
<FormGroup controlId="repeatpassword">
<FormLabel>{t("Retype password")}</FormLabel>
<FormControl
name="repeatpassword"
type="password"
ref={register}
isInvalid={!!errors.repeatpassword}
></FormControl>
<ErrorMessage
type="invalid"
name="repeatpassword"
errors={errors}
as={Form.Control.Feedback}
/>
</FormGroup>
<Button
name="registersubmit"
block
size="lg"
type="submit"
ref={register}
>
{t("Login")}
</Button>
</Form>
</FormContext>
</Modal.Body>
</Modal>
</>
);
}
Easiest way to do this (so far as I know) is to run tsc first, then run your scanner on its output. I have this in my package.json.
scripts: {
"i18n": "rm -rf tmp/i18n; npx tsc --jsx preserve --outDir tmp/i18n && npx i18next-scanner",
...
}
why compiling ts/tsx is required to extract translation ?
Because i18next-scanner doesn't parse typescript files, so it'll choke when it hits syntax it doesn't recognize. Compiling removes all that syntax.
Is there any change that i18next-scanner
will get TS support?
I haven't really went to far with this, but seems like Parser actually run over Ts files:
const fs = require('fs');
const { Parser } = require('i18next-scanner');
const parser = new Parser();
let content = '';
content = fs.readFileSync('src/components/Home/Home.tsx', 'utf-8');
parser
.parseFuncFromString(content, {
list: ['t', 'i18n.t'],
extensions: ['.ts', '.tsx'],
});
console.log(parser.get());
@ImADrafter : where I have to put above code inside where and how to run it ? `const gulp = require('gulp'); const sort = require('gulp-sort'); const scanner = require('i18next-scanner');
gulp.task('extract', function () { return gulp //.src(['src/**/.{js,ts,tsx,jsx}']) // add path of files to get scanned for extraction .src(['../../.{tsx}']) .pipe(sort()) // Sort files in stream by path .pipe( scanner({ quiet: true, lngs: ['en'], // add supported languages interpolation: { prefix: '{{', suffix: '}}', }, resource: { loadPath: '../*.json', // add your folder path to save the extracted files savePath: 'i18n/{{lng}}/{{ns}}.json', }, }), ) .pipe(gulp.dest('assets')); });
running above script `
Is there any support or solution or workaround on tsx file...
I haven't really went to far with this, but seems like Parser actually run over Ts files:
const fs = require('fs'); const { Parser } = require('i18next-scanner'); const parser = new Parser(); let content = ''; content = fs.readFileSync('src/components/Home/Home.tsx', 'utf-8'); parser .parseFuncFromString(content, { list: ['t', 'i18n.t'], extensions: ['.ts', '.tsx'], }); console.log(parser.get());
how and where I have to run this file
how to run this scanner over tsx file any solution for same, will helpful