Translation work done
This commit is contained in:
Generated
+45
@@ -7571,6 +7571,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"html-parse-stringify2": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/html-parse-stringify2/-/html-parse-stringify2-2.0.1.tgz",
|
||||
"integrity": "sha1-3FZwtyksoVi3vJFsmmc1rIhyg0o=",
|
||||
"requires": {
|
||||
"void-elements": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"html-tag-names": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/html-tag-names/-/html-tag-names-1.1.3.tgz",
|
||||
@@ -7665,6 +7673,21 @@
|
||||
"integrity": "sha1-MRYKNpMK2vH8BMYHT360FGXU7Es=",
|
||||
"dev": true
|
||||
},
|
||||
"i18next": {
|
||||
"version": "11.3.6",
|
||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-11.3.6.tgz",
|
||||
"integrity": "sha512-gaS/MwVTxOXgYSYPB3J8N3LWgOPJw7U6syjFZd2jef+kWA+0UDxf84Ai6587kTjS622/nOeCzCNPjJNQ5Mzp3Q=="
|
||||
},
|
||||
"i18next-browser-languagedetector": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-2.2.0.tgz",
|
||||
"integrity": "sha512-fKhsaJzXY2anqAPxn9bgxc5NrTcu1GnYiIwGfNFPkpfFneutHnuReb4x4suOVNMf9RTuiCxfR+UAF8aHhv89SQ=="
|
||||
},
|
||||
"i18next-xhr-backend": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/i18next-xhr-backend/-/i18next-xhr-backend-1.5.1.tgz",
|
||||
"integrity": "sha512-9OLdC/9YxDvTFcgsH5t2BHCODHEotHCa6h7Ly0EUlUC7Y2GS09UeoHOGj3gWKQ3HCqXz8NlH4gOrK3NNc9vPuw=="
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.4.23",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
|
||||
@@ -11611,6 +11634,23 @@
|
||||
"html-element-attributes": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"react-i18next": {
|
||||
"version": "7.8.0",
|
||||
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-7.8.0.tgz",
|
||||
"integrity": "sha512-NidPO6IY//vWIhL36DbFQx0rmjTJ/s4xxdvzRErGclcnka6vjUIzpEQy+NzN8fyMpI0zID3pfsV+jpBLHeAoCw==",
|
||||
"requires": {
|
||||
"hoist-non-react-statics": "^2.3.1",
|
||||
"html-parse-stringify2": "2.0.1",
|
||||
"prop-types": "^15.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"hoist-non-react-statics": {
|
||||
"version": "2.5.5",
|
||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz",
|
||||
"integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-icon-base": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-icon-base/-/react-icon-base-2.1.0.tgz",
|
||||
@@ -14007,6 +14047,11 @@
|
||||
"indexof": "0.0.1"
|
||||
}
|
||||
},
|
||||
"void-elements": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz",
|
||||
"integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w="
|
||||
},
|
||||
"warning": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz",
|
||||
|
||||
@@ -25,8 +25,12 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"color": "^3.0.0",
|
||||
"i18next": "^11.3.6",
|
||||
"i18next-browser-languagedetector": "^2.2.0",
|
||||
"i18next-xhr-backend": "^1.5.1",
|
||||
"react": "^16.4.1",
|
||||
"react-dom": "^16.4.1",
|
||||
"react-i18next": "^7.8.0",
|
||||
"styled-components": "^3.3.3"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import i18n from "i18next";
|
||||
import LanguageDetector from "i18next-browser-languagedetector";
|
||||
|
||||
import EN_TEXTS from "./translations.en.json";
|
||||
import ES_TEXTS from "./translations.es.json";
|
||||
|
||||
i18n.use(LanguageDetector).init({
|
||||
resources: {
|
||||
en: { translations: EN_TEXTS },
|
||||
es: { translations: ES_TEXTS }
|
||||
},
|
||||
fallbackLng: "en",
|
||||
ns: ["translations"],
|
||||
defaultNS: "translations",
|
||||
debug: true,
|
||||
interpolation: {
|
||||
escapeValue: false,
|
||||
format: function(value, format, lang = i18n.language) {
|
||||
if (format === "AS_DATE") {
|
||||
try {
|
||||
const dd = new Date(value);
|
||||
return new Intl.DateTimeFormat(lang).format(
|
||||
new Date(
|
||||
dd.getTime() + dd.getTimezoneOffset() * 60000
|
||||
)
|
||||
);
|
||||
} catch (e) {
|
||||
return "???";
|
||||
}
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export default i18n;
|
||||
@@ -0,0 +1,87 @@
|
||||
/* @flow */
|
||||
|
||||
import React from "react";
|
||||
|
||||
import "./styles.css";
|
||||
import i18n from "./i18n";
|
||||
const t = i18n.t.bind(i18n);
|
||||
|
||||
export class I18nForm extends React.PureComponent<
|
||||
{},
|
||||
{
|
||||
delivery: String,
|
||||
howMany: Number,
|
||||
thingColor: String
|
||||
}
|
||||
> {
|
||||
state = {
|
||||
delivery: "2018-09-22",
|
||||
howMany: 1,
|
||||
thingColor: "NC"
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
i18n.on("languageChanged", () => this.forceUpdate());
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
<h2>{t("details")}</h2>
|
||||
<button onClick={() => i18n.changeLanguage("es")}>
|
||||
ES
|
||||
</button>
|
||||
<button onClick={() => i18n.changeLanguage("en")}>
|
||||
EN
|
||||
</button>
|
||||
</div>
|
||||
<br />
|
||||
<div>{t("please enter details")}</div>
|
||||
<br />
|
||||
<div>
|
||||
{t("send it before")}:
|
||||
<input
|
||||
type="date"
|
||||
value={this.state.delivery}
|
||||
onChange={e =>
|
||||
this.setState({ delivery: e.target.value })
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
{t("number")}:
|
||||
<input
|
||||
type="number"
|
||||
min="1"
|
||||
value={this.state.howMany}
|
||||
onChange={e =>
|
||||
this.setState({
|
||||
howMany: Number(e.target.value)
|
||||
})
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
{t("color")}:
|
||||
<select
|
||||
onChange={e =>
|
||||
this.setState({ thingColor: e.target.value })
|
||||
}
|
||||
>
|
||||
<option value="NC">{t("colors.none")}</option>
|
||||
<option value="ST">{t("colors.steel")}</option>
|
||||
<option value="SD">{t("colors.sand")}</option>
|
||||
</select>
|
||||
</div>
|
||||
<br />
|
||||
<div>
|
||||
{t("summary", {
|
||||
count: this.state.howMany,
|
||||
date: this.state.delivery
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/* @flow */
|
||||
|
||||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
|
||||
import { I18nForm } from "./";
|
||||
|
||||
storiesOf("i18n form", module).add("standard", () => <I18nForm />);
|
||||
@@ -0,0 +1,4 @@
|
||||
/* @flow */
|
||||
|
||||
import { I18nForm } from "./i18nform.js";
|
||||
export { I18nForm };
|
||||
@@ -0,0 +1,2 @@
|
||||
div {
|
||||
margin-bottom: 12px; }
|
||||
@@ -0,0 +1,3 @@
|
||||
div {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"details": "Details",
|
||||
"number": "How many things?",
|
||||
"color": "Thing Color",
|
||||
"send it before": "Send the thing before",
|
||||
"please enter details": "Please, enter details for your thing:",
|
||||
"summary": "Your only thing will be there before {{date, AS_DATE}}",
|
||||
"summary_plural":
|
||||
"Your {{count}} things will be there before {{date, AS_DATE}}",
|
||||
"colors": {
|
||||
"none": "None",
|
||||
"steel": "Steel",
|
||||
"sand": "Sand"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"details": "Detalles",
|
||||
"number": "¿Cuántas cosas?",
|
||||
"color": "Color de la cosa",
|
||||
"send it before": "Enviar antes de",
|
||||
"please enter details": "Por favor, ingrese detalles para su cosa:",
|
||||
"summary": "Su única cosa llegará antes de la fecha {{date, AS_DATE}}",
|
||||
"summary_plural":
|
||||
"Sus {{count}} cosas llegarán antes del {{date, AS_DATE}}",
|
||||
"colors": {
|
||||
"none": "Ninguno",
|
||||
"steel": "Acero",
|
||||
"sand": "Arena"
|
||||
}
|
||||
}
|
||||
@@ -1,30 +1,4 @@
|
||||
/* @flow */
|
||||
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import "./styles.css";
|
||||
|
||||
export class SassButton extends React.PureComponent<{
|
||||
normal: boolean,
|
||||
buttonText: string,
|
||||
onSelect: void => void
|
||||
}> {
|
||||
static propTypes = {
|
||||
normal: PropTypes.bool.isRequired,
|
||||
buttonText: PropTypes.string.isRequired,
|
||||
onSelect: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
this.props.normal ? "normalButton" : "alertButton"
|
||||
}
|
||||
onClick={this.props.onSelect}
|
||||
>
|
||||
<span>{this.props.buttonText}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
import { SassButton } from "./sassButton";
|
||||
export { SassButton };
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/* @flow */
|
||||
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import "./styles.css";
|
||||
|
||||
export class SassButton extends React.PureComponent<{
|
||||
normal: boolean,
|
||||
buttonText: string,
|
||||
onSelect: void => void
|
||||
}> {
|
||||
static propTypes = {
|
||||
normal: PropTypes.bool.isRequired,
|
||||
buttonText: PropTypes.string.isRequired,
|
||||
onSelect: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
this.props.normal ? "normalButton" : "alertButton"
|
||||
}
|
||||
onClick={this.props.onSelect}
|
||||
>
|
||||
<span>{this.props.buttonText}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,63 +1,4 @@
|
||||
/* @flow */
|
||||
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import styled from "styled-components";
|
||||
import Color from "color";
|
||||
|
||||
import {
|
||||
NORMAL_TEXT,
|
||||
NORMAL_COLOR,
|
||||
ALERT_TEXT,
|
||||
ALERT_COLOR
|
||||
} from "./constants";
|
||||
|
||||
const makeSpan = props => `
|
||||
span {
|
||||
color: ${props.normal ? NORMAL_TEXT : ALERT_TEXT};
|
||||
font-weight: bold;
|
||||
}
|
||||
`;
|
||||
|
||||
const BasicStyledDiv = styled.div`
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
padding: 5px 10px;
|
||||
border-radius: 3px;
|
||||
`;
|
||||
|
||||
const StyledDiv = BasicStyledDiv.extend`
|
||||
background-color: ${props =>
|
||||
props.normal ? NORMAL_COLOR : ALERT_COLOR};
|
||||
&:hover {
|
||||
background-color: ${props =>
|
||||
Color(props.normal ? NORMAL_COLOR : ALERT_COLOR)
|
||||
.darken(0.25)
|
||||
.string()};
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
${props => makeSpan(props)};
|
||||
`;
|
||||
|
||||
export class StyledButton extends React.PureComponent<{
|
||||
normal: boolean,
|
||||
buttonText: string,
|
||||
onSelect: void => void
|
||||
}> {
|
||||
static propTypes = {
|
||||
normal: PropTypes.bool.isRequired,
|
||||
buttonText: PropTypes.string.isRequired,
|
||||
onSelect: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<StyledDiv
|
||||
normal={this.props.normal}
|
||||
onClick={this.props.onSelect}
|
||||
>
|
||||
<span>{this.props.buttonText}</span>
|
||||
</StyledDiv>
|
||||
);
|
||||
}
|
||||
}
|
||||
import { StyledButton } from "./styledButton";
|
||||
export { StyledButton };
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/* @flow */
|
||||
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import styled from "styled-components";
|
||||
import Color from "color";
|
||||
|
||||
import {
|
||||
NORMAL_TEXT,
|
||||
NORMAL_COLOR,
|
||||
ALERT_TEXT,
|
||||
ALERT_COLOR
|
||||
} from "./constants";
|
||||
|
||||
const makeSpan = props => `
|
||||
span {
|
||||
color: ${props.normal ? NORMAL_TEXT : ALERT_TEXT};
|
||||
font-weight: bold;
|
||||
}
|
||||
`;
|
||||
|
||||
const BasicStyledDiv = styled.div`
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
padding: 5px 10px;
|
||||
border-radius: 3px;
|
||||
`;
|
||||
|
||||
const StyledDiv = BasicStyledDiv.extend`
|
||||
background-color: ${props =>
|
||||
props.normal ? NORMAL_COLOR : ALERT_COLOR};
|
||||
&:hover {
|
||||
background-color: ${props =>
|
||||
Color(props.normal ? NORMAL_COLOR : ALERT_COLOR)
|
||||
.darken(0.25)
|
||||
.string()};
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
${props => makeSpan(props)};
|
||||
`;
|
||||
|
||||
export class StyledButton extends React.PureComponent<{
|
||||
normal: boolean,
|
||||
buttonText: string,
|
||||
onSelect: void => void
|
||||
}> {
|
||||
static propTypes = {
|
||||
normal: PropTypes.bool.isRequired,
|
||||
buttonText: PropTypes.string.isRequired,
|
||||
onSelect: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<StyledDiv
|
||||
normal={this.props.normal}
|
||||
onClick={this.props.onSelect}
|
||||
>
|
||||
<span>{this.props.buttonText}</span>
|
||||
</StyledDiv>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/* @flow */
|
||||
|
||||
import React from "react";
|
||||
|
||||
const getWindowSize = () => ({
|
||||
resized_w_h: window.innerWidth + "x" + window.innerHeight
|
||||
});
|
||||
|
||||
export const makeResize = Comp => {
|
||||
// eslint-disable-next-line react/display-name
|
||||
return class extends React.Component {
|
||||
state = getWindowSize();
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.componentIsResizing = this.componentIsResizing.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.addEventListener("resize", this.componentIsResizing);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener("resize", this.componentIsResizing);
|
||||
}
|
||||
|
||||
componentIsResizing() {
|
||||
this.setState(getWindowSize());
|
||||
}
|
||||
|
||||
render() {
|
||||
return <Comp {...this.props} {...this.state} />;
|
||||
}
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user