diff --git a/.babelrc b/.babelrc index 9fed7ca1d..f483883a9 100644 --- a/.babelrc +++ b/.babelrc @@ -5,6 +5,7 @@ "@babel/preset-typescript" ], "plugins": [ + "@babel/plugin-proposal-numeric-separator", "@babel/plugin-proposal-class-properties", [ "@babel/plugin-proposal-decorators", @@ -16,8 +17,10 @@ [ "react-intl", { + "extractFromFormatMessageCall": true, "messagesDir": "build/locale/" } ] - ] + ], + "ignore": ["**/*.test.ts", "**/*.test.tsx", "src/storybook"] } diff --git a/package-lock.json b/package-lock.json index cb0710d03..694d3d59c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -453,6 +453,16 @@ "@babel/plugin-syntax-json-strings": "^7.2.0" } }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.2.0.tgz", + "integrity": "sha512-DohMOGDrZiMKS7LthjUZNNcWl8TAf5BZDwZAH4wpm55FuJTHgfqPGdibg7rZDmont/8Yg0zA03IgT6XLeP+4sg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-numeric-separator": "^7.2.0" + } + }, "@babel/plugin-proposal-object-rest-spread": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz", @@ -538,6 +548,15 @@ "@babel/helper-plugin-utils": "^7.0.0" } }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.2.0.tgz", + "integrity": "sha512-DroeVNkO/BnGpL2R7+ZNZqW+E24aR/4YWxP3Qb15d6lPU8KDzF8HlIUIRCOJRn4X77/oyW4mJY+7FHfY82NLtQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, "@babel/plugin-syntax-object-rest-spread": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", diff --git a/package.json b/package.json index 579664b39..b62e44797 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,7 @@ "@babel/core": "^7.5.4", "@babel/plugin-proposal-class-properties": "^7.5.0", "@babel/plugin-proposal-decorators": "^7.4.4", + "@babel/plugin-proposal-numeric-separator": "^7.2.0", "@babel/plugin-proposal-object-rest-spread": "^7.5.4", "@babel/preset-env": "^7.5.4", "@babel/preset-react": "^7.0.0", @@ -163,7 +164,10 @@ }, "scripts": { "build": "webpack -p", - "build-messages": "babel src/**/*.{ts,tsx} -o build/dashboard.bundle.js && rip json2pot \"build/locale/**/*.json\" -c id -o locale/messages.pot", + "extract-json-messages": "babel src 'src/**/*.{ts,tsx}' -o build/dashboard.bundle.js", + "extract-pot-messages": "rip json2pot \"build/locale/**/*.json\" -c description -o locale/messages.pot", + "extract-messages": "npm run extract-json-messages && npm run extract-pot-messages", + "build-messages": "rip po2json 'locale/**/*.po' -m 'build/locale/**/*.json' -o 'locale' -c 'description'", "build-types": "apollo client:codegen --target=typescript types --globalTypesFile=src/types/globalTypes.ts", "generate-component": "plop --plopfile .plop/plopfile.js", "lint": "tslint 'src/**/*.{ts,tsx}'", diff --git a/src/components/Date/DateProvider.tsx b/src/components/Date/DateProvider.tsx index 90226eb0f..802b3f4a3 100644 --- a/src/components/Date/DateProvider.tsx +++ b/src/components/Date/DateProvider.tsx @@ -18,7 +18,7 @@ export class DateProvider extends React.Component<{}, DateProviderState> { componentDidMount() { this.intervalId = window.setInterval( () => this.setState({ date: Date.now() }), - 10_000 + 10000 ); } diff --git a/src/components/Locale/Locale.tsx b/src/components/Locale/Locale.tsx index bcc5fb7b7..93abbfad5 100644 --- a/src/components/Locale/Locale.tsx +++ b/src/components/Locale/Locale.tsx @@ -1,5 +1,7 @@ +import { LOCALE_URI } from "@saleor/config"; import React from "react"; import { IntlProvider } from "react-intl"; +import urlJoin from "url-join"; export type LocaleContextType = string; export const LocaleContext = React.createContext("en"); @@ -7,11 +9,32 @@ export const LocaleContext = React.createContext("en"); const { Consumer: LocaleConsumer, Provider } = LocaleContext; const LocaleProvider = ({ children }) => { - const [locale] = React.useState(navigator.language); + const [localeIndex, setLocaleIndex] = React.useState(0); + const [messages, setMessages] = React.useState({}); + + const locale = navigator.languages[localeIndex]; + + React.useEffect(() => { + async function fetchLocale() { + if (locale) { + const res = await fetch(urlJoin(LOCALE_URI, `${locale}.json`), { + credentials: "same-origin", + mode: "cors" + }); + if (res.ok) { + const localeData = await res.json(); + setMessages(localeData); + } else { + setLocaleIndex(localeIndex + 1); + } + } + } + fetchLocale(); + }, [localeIndex]); return ( - - {children} + + {children} ); }; diff --git a/src/config.ts b/src/config.ts index ac5f694cd..e24fdbbe8 100644 --- a/src/config.ts +++ b/src/config.ts @@ -3,6 +3,7 @@ import { ListSettings, ListViews } from "./types"; export const APP_MOUNT_URI = process.env.APP_MOUNT_URI || "/"; export const API_URI = process.env.API_URI || "/graphql/"; +export const LOCALE_URI = process.env.LOCALE_URI || "/"; export const DEFAULT_INITIAL_SEARCH_DATA: SearchQueryVariables = { after: null, diff --git a/src/intl.ts b/src/intl.ts new file mode 100644 index 000000000..64cd7b86e --- /dev/null +++ b/src/intl.ts @@ -0,0 +1,28 @@ +import { defineMessages } from "react-intl"; + +export const commonMessages = defineMessages({ + cancel: { + defaultMessage: "Cancel", + id: "cancel" + }, + confirm: { + defaultMessage: "Confirm", + id: "confirm" + }, + save: { + defaultMessage: "save", + id: "save" + }, + savedChanges: { + defaultMessage: "Saved changes", + id: "savedChanges" + } +}); + +export const sectionNames = defineMessages({ + attributes: { + defaultMessage: "attributes", + description: "attributes section name", + id: "attributes" + } +}); diff --git a/webpack.config.js b/webpack.config.js index c49817f26..8b4eb4755 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -21,7 +21,8 @@ const htmlWebpackPlugin = new HtmlWebpackPlugin({ }); const environmentPlugin = new webpack.EnvironmentPlugin([ "APP_MOUNT_URI", - "API_URI" + "API_URI", + "LOCALE_URI" ]); const dashboardBuildPath = "build/dashboard/";